2011-01-10 15 views
16

Si intenta compilar la consulta siguiente en Visual Basic .NET, falla.¿Por qué no puedo proyectar ToString() en VB?

From x In {1, 2} Select x.ToString() 

El error dado por el compilador es:

rango de nombres de variable no puede coincidir con el nombre de un miembro de la clase 'Objeto'.

No hay nada malo con el C# consulta equivalente, sin embargo:

from x in new[]{1, 2} select x.ToString() 

Esto no sucede con la sobrecarga de ToString que tiene un formato (que es un miembro de Int32, no objeto). Sucede con otros miembros de Object, siempre que no tomen un argumento: con GetType y GetHashCode falla; con Equals (objeto) compila.

¿Por qué existe esta restricción y qué alternativas puedo usar?

+0

Interesante. 'From x In {1, 2} Select x.ToString (" d ")' se compila, probablemente porque 'Object' no lo tiene. No conozco ningún VB, pero parece extraño. – Kobi

+0

@Kobi: Supongo que su ejemplo compila porque no hay un miembro 'ToString' en' Object' que tome un argumento. Por qué eso sería un problema es lo que me desconcierta. –

+0

Creo que es porque obviamente no es una propiedad cuando se invoca con un argumento, y por lo tanto, VB sabe que no lo está usando para crear un objeto anónimo con una propiedad 'ToString', mientras que si alguien se equivoca. (Que podría haber sido lo que estabas diciendo - No soy un experto en VB.) – Rup

Respuesta

10

Así es como lo entiendo. Considere el siguiente código:

Dim q = From x In {"Bob", "Larry"} 
     Select x.Length 
     Select Length * 2 

En la consulta anterior, el nombre de la variable es Lengthautomáticamente "adivinado" para usted por el compilador de VB basado en la expresión x.Length. Ahora bien, es cierto que no lo hizo pregunte para esto; es solo una característica que se proporciona ya sea que te guste o no. Pero ahora considere esto:

Dim q = From x In {"Bob", "Larry"} 
     Select (x.Length) 
     Select Length * 2 

Lo anterior no compilará porque la expresión dentro de la primera Select cláusula no es tan simple como en el primer caso (aunque no lo crean); los paréntesis complican las cosas lo suficiente para que el compilador no elija el nombre Length; en cambio, genera un nombre que no se puede utilizar desde el código.

Así que básicamente lo que está pasando con ToString() es que esta expresión es lo suficientemente simple como para que el compilador utiliza para generar un nombre de variable, lo que podría utilizarse si la consulta se amplió para hacer uso de esta variable, por ejemplo,:

Dim q = From x In { 1, 2 } 
     Select x.ToString() 
     Select ToString.Length 

Sin embargo, ToString no es un nombre válido para una variable ya que es un miembro de System.Object (¿por qué esto podría ser el caso de variables dentro de las consultas LINQ, pero no para las variables locales estándar, que no podía decir)

+0

Gosh, odio esta característica. Veo cómo puede ser útil, pero el problema que crea es alucinante y mi ejemplo está lejos de ser un caso de uso poco frecuente. No veo cómo se podría proporcionar un mensaje de error revelador, pero creo que el compilador debería "adivinar" automáticamente el nombre si no fuera un nombre válido. –

5

Aunque no puedo ofrecer detalles acerca del error, una solución simple:

From x In {1, 2, 3} Let str = x.ToString() Select str 

Por lo que vale la pena, cuando se tiene la siguiente línea:

Dim b = From num In {1, 2, 3} Select num.ToString("d") 

es recopila y decompiles a (usando Reflector, a C#):

public class Class1 
{ 
    [CompilerGenerated] 
    private static string _Lambda$__1(int num) 
    { 
     return num.ToString("d"); 
    } 

    public void Test1() 
    { 
     IEnumerable<string> b = new int[] { 1, 2, 3 } 
      .Select<int, string>(new Func<int, string>(Class1._Lambda$__1)); 
    } 
} 

no parece haber ninguna clase anónima al ong el camino.

34

No podría decirte exactamente por qué VB tiene esta ridiculez, pero la solución simple es poner la llamada al método en parens.

Dim q = From x In {1, 2} Select (x.ToString()) 
+6

Mi cabeza acaba de explotar. –

+0

Gracias tnyfst.He hecho implementado una mejora de código sugerida de resharper pero de repente arrojando error.then puse el paréntesis como lo sugirió uy funciona mucho. Gracias –

Cuestiones relacionadas