tipos - Variable no inicializada en C#
tipos de variables en c sharp (8)
A las variables locales no se les asigna un valor por defecto. Tienes que inicializarlos antes de usarlos. Puedes inicializar explícitamente a null
sin embargo:
public Foo()
{
Bar bar = null;
if (null == bar)
{
}
}
Tengo el siguiente código:
class Foo
{
public Foo()
{
Bar bar;
if (null == bar)
{
}
}
}
class Bar { }
Los gurús del código ya verán que esto da un error. Es posible que la barra no se inicialice antes de la instrucción if.
Así que ahora me pregunto: ¿cuál es el valor de la barra, no debería ser nulo? ¿No están puestos en nulo? (¿puntero nulo?)
A las variables locales no se les asigna un valor predeterminado, ni siquiera un null
.
Además de la "corrección", la inicialización de la variable local también está relacionada con el proceso de verificación del CLR.
Para más detalles, vea mi respuesta a esta pregunta similar: ¿Por qué las variables locales deben tener valores iniciales?
El valor de la bar
no está definido. Hay espacio asignado para él en la pila, pero el espacio no se inicializa a ningún valor, por lo que contiene todo lo que estaba allí antes.
(Sin embargo, la variable local podría optimizarse para utilizar un registro en lugar de espacio de pila, pero aún no está definido).
El compilador no le permitirá usar el valor indefinido, tiene que poder determinar que la variable se inicializa antes de poder usarla.
A modo de comparación, VB inicializa las variables locales. Si bien esto puede ser práctico a veces, también puede significar que usted usa involuntariamente una variable antes de darle un valor significativo, y el compilador no puede determinar si es lo que se proponía hacer o no.
Los campos (variables en clases / estructuras) se inicializan en null
/ zero / etc. Variables locales ... bueno, ya que (por "asignación definida") no se puede acceder a ellas sin asignar, no hay una forma sensata de responder; Simplemente, no está definido ya que es imposible. Creo que resultan ser null
/ cero / etc (que se pueden obtener al hackear parte del código mediante la generación dinámica de IL), pero eso es un detalle de la implementación.
Para obtener información, aquí hay algunos códigos que muestran el valor de una variable no inicializada formalmente:
using System;
using System.Reflection.Emit;
static class Program
{
delegate void Evil<T>(out T value);
static void Main()
{
MakeTheStackFilthy();
Test();
}
static void Test()
{
int i;
DynamicMethod mthd = new DynamicMethod("Evil", null, new Type[] { typeof(int).MakeByRefType()});
mthd.GetILGenerator().Emit(OpCodes.Ret); // just return; no assignments
Evil<int> evil = (Evil<int>)mthd.CreateDelegate(typeof(Evil<int>));
evil(out i);
Console.WriteLine(i);
}
static void MakeTheStackFilthy()
{
DateTime foo = new DateTime();
Bar(ref foo);
Console.WriteLine(foo);
}
static void Bar(ref DateTime foo)
{
foo = foo.AddDays(1);
}
}
El IL solo hace una "ret" - nunca asigna nada.
No importa porque ningún compilador que implemente C # compileble.
Si hubiera un valor predeterminado, entonces sería compilable. Pero no hay ninguno para las variables locales.
No, las variables locales no se configuran automáticamente en 0 (predeterminado).
Pero como tú (siempre) obtienes ese error, realmente no importa. Si tuviera otro valor, el compilador nunca te dejaría descubrirlo.
No deben confundirse con las variables de campo (miembros de la clase), se inicializan al valor predeterminado de su tipo (0 / null / false / ...).
No, las variables locales no tienen un valor por defecto 1 . Tienen que ser asignados definitivamente antes de leerlos. Esto reduce la posibilidad de que utilices una variable a la que crees que le has dado un valor razonable, cuando en realidad tiene algún valor predeterminado. Esto no se puede hacer, por ejemplo, o las variables estáticas porque no se sabe en qué orden se llamarán los métodos.
Consulte la sección 5.3 de la especificación C # 3.0 para obtener más detalles sobre la asignación definida.
Tenga en cuenta que esto no tiene nada que ver con que esta sea una variable de tipo de referencia. Esto no podrá compilar de la misma manera:
int i;
if (i == 0) // Nope, i isn''t definitely assigned
{
}
1 En lo que respecta al lenguaje, de todas formas ... claramente la ubicación de almacenamiento en la memoria tiene algo , pero es irrelevante y específica para la implementación. Hay una manera de averiguar cuál es ese valor, creando un método con un parámetro de out
pero luego usando IL para ver el valor de ese parámetro dentro del método, sin haberle dado otro valor. Al CLR no le importa eso en absoluto. Luego, puede llamar a ese método pasando una variable no asignada definitivamente, y he aquí que puede detectar el valor, que es, probablemente, el valor de "todos los ceros" básicamente.
Sospecho que la especificación de la CLI obliga a las variables locales a tener un valor predeterminado, pero tendría que verificarlo. A menos que estés haciendo cosas malas como las anteriores, no debería importarte en C #.