valores - ¿Por qué la variable local C#debe asignarse directamente, incluso si es un valor predeterminado?
pasar objetos como parametros en c# (4)
Básicamente, esto es lo que MS decidió.
Si quieres más, puedes leer aquí y consultar el Blog de Eric Lippert
La razón por la cual esto es ilegal en C # es porque el uso de un local no asignado tiene una alta probabilidad de ser un error.
Si miras el siguiente ejemplo:
public void TestLocalValuesAssignment()
{
int valueVariable; // = default(int) suits fine
string refType; // null suits fine as well
try
{
valueVariable = 5;
refType = "test";
}
catch (Exception){}
Console.WriteLine("int value is {0}", valueVariable);
Console.WriteLine("String is {0}", refType);
}
se puede ver fácilmente, que las variables valueVariable
y refType
pueden refType
antes de su uso en Console.WriteLine()
. El compilador nos cuenta sobre eso con errores:
Error 1 Use of unassigned local variable ''valueVariable''
Error 2 Use of unassigned local variable ''refType''
Este es un caso generalizado y hay muchas respuestas sobre cómo solucionarlo (posibles soluciones comentadas).
Lo que no puedo entender es ¿por qué existe tal comportamiento? ¿Cómo las variables locales son diferentes de los campos de clase , donde los últimos obtienen el valor predeterminado si no están asignados (nulo para los tipos de referencia y el valor por defecto correspondiente para los tipos de valor)? ¿Tal vez hay un ejemplo o un caso de esquina que explica por qué se elige ese comportamiento de compilador?
Cuando haces algo que parece estúpido , como leer de una variable que nunca has asignado, básicamente hay dos cosas que el compilador puede hacer:
- Le dará un diagnóstico llamando su atención sobre lo que probablemente sea un error.
- Haz algo arbitrario.
Dado que la opción # 1 lo ayuda a encontrar errores, es preferible, especialmente cuando la solución para decirle al compilador "No, me refiero al uso del valor predeterminado original" es tan simple como agregar = 0
, = null
o = default(T)
.
En cuanto a por qué los miembros de la clase no funcionan de la misma manera, es porque esto no se puede verificar en tiempo de compilación (debido a la miríada de órdenes diferentes que los diferentes métodos podrían llamarse). Habría un costo de tiempo de ejecución de las banderas, si cada miembro había sido asignado, y la prueba de esas banderas.
Tenga en cuenta que el compilador impone la restricción sobre los miembros de struct de una forma que es fácil de verificar en tiempo de compilación. A saber, cada constructor debe asignar cada miembro.
En realidad, su código debería estar bien, pero por interpretación estricta, hay una ruta de código que puede dejar sus variables sin asignar antes de su uso. El bloque try introduce la posibilidad de que el código dentro del bloque no se ejecute (si se lanza una excepción), pero aún ejecuta el código más allá del catch (porque no hay nada en el catch como return o throw para evitar el resto de tu método de ejecución si se lanza una excepción en el intento ).
Si se refiere a la diferencia entre inicializar campos "struct" e inicializar campos de clases, por ejemplo:
public class A
{
}
MyMethod()
{
int myInt; // Initialized to zero, yes, but not yet assigned.
// An error to use this before assigning it.
A myA; // defaults to null, which may be a valid initial state, but still unassigned.
// Also an error to use this before assigning it.
A oneMoreA = null; // Same value as default, but at least intention is clear.
A anotherA = new A(); // What is or is not happening in the constructor is a separate issue.
// At least anotherA refers to an actual instance of the class.
Se describe en la especificación c #:
5.1.7 Variables locales
Una variable local introducida por una declaración de variable local no se inicializa automáticamente y, por lo tanto, no tiene ningún valor predeterminado. A los efectos de una verificación de asignación definida, una variable local introducida por una declaración de variable local se considera inicialmente no asignada. Una declaración de variable local puede incluir un inicializador de variable local , en cuyo caso la variable se considera definitivamente asignada solo después de la expresión de inicialización (§5.3.3.4).
Dentro del alcance de una variable local introducida por una declaración de variable local , es un error en tiempo de compilación referirse a esa variable local en una posición textual que precede a su declarador de variable local . Si la declaración de variable local es implícita (§8.5.1), también es un error referirse a la variable dentro de su declarador de variable local .