2011-09-23 4 views
10

Tengo una observación sobre struct. Cuando declaro una propiedad en Struct y si no inicializar la Struct entonces me da el error abajo - "El uso de empStruct variable local no asignada"El compilador da error cuando struct no se inicializa y si tratamos de acceder a la propiedad pero no con la variable

pseduo Code-

struct EmpStruct 
{ 
    private int firstNumber; 
    public int FirstNumber 
    { 
     get { return firstNumber; } 
     set { firstNumber = value; } 
    } 

    public int SecondNumber; 

} 

Program.cs-

EmpStruct empStruct; 
empStruct.FirstNumber = 5; 

Pero cuando declaro una variable pública, el código anterior funciona.

EmpStruct empStruct; 
empStruct.SecondNumber; 

Así que mi pregunta es ¿por qué compilador no da error al intentar acceder a la variable. (En el caso de la clase que le dará el error).

+3

Quien esté bajando la votación de todas las respuestas, deje comentarios sobre por qué son incorrectas. Los estoy votando, ya que tienen sentido según la publicación de Punit ... –

+1

@bemused: Todos están equivocados. Y he dejado comentarios explicando por qué. – jason

Respuesta

11

Hay una gran cantidad de confusión en este hilo.

El principio es este: hasta que se asignen definitivamente todos los campos de una instancia de struct, no puede invocar ninguna propiedad o método en la instancia.

Es por eso que su primer bloque de código no se compilará. Está accediendo a una propiedad sin asignar definitivamente todos los campos.

El segundo bloque de código se compila porque está bien acceder a un campo sin asignar definitivamente todos los campos.

Una forma de asignar definitivamente una struct es decir

EmpStruct empStruct = new EmpStruct(); 

Esto invoca el constructor sin parámetros por defecto para EmpStruct que sin duda asignar todos los campos.

La sección relevante de la especificación es §5.3 en Asignación Definitiva. Y desde el ejemplo de §11.3.8

Sin función miembro de instancia (incluyendo los descriptores de acceso set para las propiedades X y Y) se pueden llamar hasta que todos los campos de la estructura están construidas han sido definitivamente asignado.

Sería más útil (ejem, Eric Lippert!) Si el mensaje de error del compilador estaban en la línea de

El uso de no definitivamente asignado variable local empStruct.

Luego queda claro qué buscar en la especificación o en Google.

Ahora, tenga en cuenta que ha definido una estructura mutable. Esto es peligroso y malvado. No deberías hacerlo En su lugar, agregue un constructor público que le permita asignar definitivamente firstNumber y secondNumber, y eliminar el public setter del EmpStruct.FirstNumber.

+0

+1, Buena captura en cuanto a los accesores de propiedad! – sll

+0

Gracias por borrar el hilo. Supongo que fue la redacción de la pregunta lo que confundió a todos. –

+0

gracias tiene sentido – Punit

3

campos Respecto C# Especificación lengua dice:

10.5.4 inicialización campo

El valor inicial de un campo, ya se trate de un campo estático o un campo ejemplo, es el valor predeterminado (§5.2) del tipo de campo. Es no es posible observar el valor de un campo antes de que este defecto se ha producido inicialización, y un campo es por lo tanto nunca

11.3.4 Los valores por defecto”sin inicializar

Sin embargo, desde las estructuras son tipos de valores que no pueden ser nulos, el valor predeterminado de una estructura es el valor producido al establecer todos los campos de tipo de valor a su valor predeterminado y todos los campos de tipo de referencia a nulo. El valor predeterminado de una estructura corresponde al valor devuelto por el constructor predeterminado de la estructura (§4.1.2).

PS: en el caso de la clase que da error porque el valor de tipo de referencia por defecto es nulo

+0

Esto no es relevante. No explica el motivo del error. – jason

+0

@Jason: es relevante en términos de casos de campo y de clase, pero no es un error relacionado con la propiedad. Todavía no puedo encontrar una respuesta en la especificación – sll

+0

Lo siento, no es relevante en absoluto. El motivo del error tiene que ver con la falta de asignación definida a 'EmpStruct'. Las secciones de la especificación que citó no hacen referencia a la asignación definitiva. Ver §5.3 y §11.3.8. – jason

1

En el primer ejemplo, el código no funciona porque las variables locales tienen que ser inicializado antes de poder utilizarlos . No existe un valor predeterminado; deben inicializarse primero. Siempre debe inicializar cada variable local antes de poder usarla. Por ejemplo:

EmpStruct empStruct = new EmpStruct(); 
empStruct.FirstNumber = 5; 

Los campos de una clase no tienen esta misma restricción. Si no los inicializa explícitamente, se inicializarán automáticamente con los valores predeterminados. En efecto, el tiempo de ejecución llama automáticamente a "nuevo EmpStruct()" en el campo de su clase. Es por eso que tu segundo ejemplo funciona.

+0

Esto no tiene ningún sentido.¿Por qué el compilador llamará 'nuevo EmpStruct' en el segundo bloque pero no el primero? Esta respuesta no explica por qué hay una diferencia entre los dos bloques de código. – jason

+0

Ah ... Creo que tuve dificultades para entender la pregunta original ... Pensé que estaba hablando de usar una estructura como variable local vs. usar una estructura como campo. –

1

Unos pocos ejemplos de código podrían ayudar a aclarar esto mejor:

// This works because you assign both fields before accessing anything 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
empStruct.firstNumber = 1; // I made this public 
empStruct.FirstNumber = 3; 
Console.WriteLine(empStruct.FirstNumber); 
Console.WriteLine(empStruct.SecondNumber); 

// This fails because you can't use properties before assigning all the variables 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
empStruct.FirstNumber = 3; 

// This works because you are only accessing a field that the compiler knows you've assigned 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
Console.WriteLine(empStruct.SecondNumber); 

// This fails because you haven't assigned the field before it gets accessed. 
EmpStruct empStruct; 
Console.WriteLine(empStruct.SecondNumber); 

El punto es, el compilador sabe exactamente lo que sucederá cuando se asigna un campo. Pero cuando asigna una propiedad, puede acceder a cualquier cantidad de otros campos en el struct. El compilador no está seguro. Por lo tanto, requiere que tenga todos los campos asignados antes de poder acceder a una propiedad.

Cuestiones relacionadas