2010-12-16 11 views
23
class A 
{ 
    A() 
    { 
     var x = 5; // this is allowed 
    } 

    var _x = 5; // the compiler is unhappy 
} 

Supongo que el compilador debe poder deducir el tipo para la variable miembro de la misma manera que lo hace para la variable local. Entonces, ¿cuál es la diferencia?¿Por qué los campos de clase no pueden ser var?

+0

porque no puede usar var de un método. No puede declarar una var global y dado que los constructores también son métodos, no obtiene el error. – Pabuc

+1

@Pabuc: ¿De qué estás hablando? – SLaks

+7

Creo que casi todas las explicaciones a continuación son basura, a excepción de las referencias fugaces a [la publicación de Lippert] (http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var- on-fields.aspx). La respuesta: porque es mucho trabajo dada la forma en que el compilador se construye hoy. Es un problema interno. –

Respuesta

24

Eric Lippert respondido a su pregunta aquí: Why no var on fields?

Básicamente, para el caso general que sería necesario volver a escribir el compilador de C#, como la forma en que lo hace actualmente la inferencia de tipos no funcionaría para los ciclos de la variable var campo asignaciones.

7

La palabra clave var se diseñó para tipos anónimos, que solo se pueden usar dentro de un método.

Además, estás equivocado; el compilador no siempre puede deducir un campo var.

¿Qué pasa si se compila la siguiente:

class A { 
    public readonly var value = B.value; 
} 

class B { 
    public readonly var value = B.value; 
} 

Esta situación es imposible recrear con variables locales, ya que una variable no puede ser referenciado antes de que sea definido.

El problema general aquí es que le está pidiendo al compilador que consuma información de tipo mientras todavía está generando esa información.
Eric Lippert explains in greater depth.

+8

Si la función var solo se diseñó para tipos anónimos, no permitiría su uso con variables regulares. El propio Eric Lippert dice que le gustaría que esta característica funcione con los campos, pero tienen problemas con la implementación, no con el conflicto de diseño. – Stilgar

+0

Usted: _ tipos anónimos, que solo se pueden usar dentro de un método_ Se puede preguntar por qué los tipos anónimos no se pueden usar en los campos. Es posible tener un inicializador de campo (a un campo de tipo explícito 'object' o' dynamic') que asigna una instancia de tipo anónimo a ese campo. P.ej. 'objeto estático Field = new {Cost = 3.5m, Age = 2,};'. También es posible tener un campo cuyo tipo de tiempo de compilación es un parámetro de tipo, como 'T campo estático' donde' T' es de una clase que contiene genérico, y luego hacer que 'T' se convierta en un tipo anónimo por inferencia de tipo en un método de fábrica. –

+0

@JeppeStigNielsen: Me refiero a un campo de tipo anónimo (en tiempo de compilación). – SLaks

0

Pero para un

var a = SomeMethod();

el compilador primero necesita saber el retornado del SomeMethod() y aún no lo sabe en este punto.

Ver: http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx

+0

Y, sin embargo, normalmente puede escribir 'var X = SomeMethod()' dentro del constructor ... –

+0

porque los consturctors son métodos. – Pabuc

+0

@Michael: dentro del constructor, los miembros de la clase ya han sido analizados. – SLaks

0

Esta es una suposición, pero la inicialización de campos de nivel de clase debe hacerse como parte del proceso de inicialización (constructor) para un tipo, mientras que la inicialización de una variable de nivel método sucede cuando el El marco de pila del método está construido. Quizás la distinción se relaciona con la forma en que se compilan estos procesos (cómo se crea su implementación) dentro del marco.

+0

Incorrecto. 'var' es un concepto puramente de tiempo de compilación y no tiene nada que ver con la ejecución del inicializador. – SLaks

+0

@Slaks, la redacción no estaba clara. Editado para corregir –

2

Veo dos razones:

  1. Podría ser conveniente para hacer la declaración de tipos en una interfaz pública explícita
  2. Es difícil de implementar. El compilador C# compila en múltiples fases.
    Al principio analiza todo aparte de los cuerpos de métodos para que sepa todo lo que esté fuera de los cuerpos de las funciones. Luego puede usar esa información para compilar cuerpos de métodos individualmente. Lo que sucede al compilar un cuerpo de método no tiene mucho efecto en lo que sucede al compilar otros cuerpos de método.
    Si puede usar var para campos, el cuerpo de expresión del inicializador de campo afectará el tipo de campo y, por lo tanto, muchos otros métodos. Por lo tanto, no encaja bien en el diseño del compilador.
Cuestiones relacionadas