Inicialización de campos de instancia frente a variables locales

Siempre me he preguntado por qué en el siguiente ejemplo está bien no inicializar el campo de instancia (confiando que tendrá su valor predeterminado) y acceder a él, mientras que las variables locales aparentemente deben inicializarse, incluso si lo inicializo al valor predeterminado de todos modos lo conseguiría …

public class TestClass { private bool a; public void Do() { bool b; // That would solve the problem: = false; Console.WriteLine(a); Console.WriteLine(b); //Use of unassigned local variable 'b' } } 

Para variables locales, el comstackdor tiene una buena idea del flujo: puede ver una “lectura” de la variable y una “escritura” de la variable, y probar (en la mayoría de los casos) que la primera escritura ocurrirá antes de la primera lectura .

Este no es el caso con las variables de instancia. Considere una propiedad simple: ¿cómo sabe si alguien la configurará antes de obtenerla? Eso hace que, básicamente, no sea factible aplicar reglas sensatas, por lo que deberá asegurarse de que todos los campos estén establecidos en el constructor, o permitir que tengan valores predeterminados. El equipo C # eligió la última estrategia.

Se rige por las reglas de Asignación Definitiva en C #. La variable debe asignarse definitivamente antes de acceder a ella.

5.3 Asignación definitiva

En una ubicación dada en el código ejecutable de un miembro de función, se dice que una variable está definitivamente asignada si el comstackdor puede demostrar, mediante un análisis de flujo estático particular (§5.3.3), que la variable se ha inicializado automáticamente o se ha el objective de al menos una tarea.

5.3.1 variables asignadas inicialmente

Las siguientes categorías de variables se clasifican como inicialmente asignadas:

  • Variables estáticas

  • Variables de instancia de instancias de clase.

  • Variables de instancia de variables de estructura asignadas inicialmente.

  • Elementos de matriz

  • Parámetros de valor

  • Parámetros de referencia.

  • Variables declaradas en una cláusula catch o en una statement foreach.

5.3.2 Variables inicialmente sin asignar

Las siguientes categorías de variables se clasifican como inicialmente sin asignar:

  • Variables de instancia de variables de estructura inicialmente no asignadas.

  • Parámetros de salida, incluida esta variable de constructores de instancias struct.

  • Variables locales, excepto las declaradas en una cláusula catch o en una statement foreach.

Cuando se asigna un trozo de memoria para una nueva instancia de objeto, el tiempo de ejecución escribe ceros en todo el bloque, asegurando que el nuevo objeto comience en un estado conocido: por eso los enteros predeterminan a 0, doblan por defecto a 0.0, punteros y referencias de objetos anular, y así sucesivamente.

En teoría, sería posible hacer lo mismo para astackr cuadros asignados como parte de llamadas a métodos. La sobrecarga, sin embargo, sería alta, ralentizaría drásticamente las llamadas a otros métodos y, por lo tanto, no se intentará.

Las variables de instancia tienen un valor predeterminado. A partir de la especificación C # 3.0:

5.1.2.1 Variables de instancia en clases

Una variable de instancia de una clase entra en existencia cuando se crea una nueva instancia de esa clase, y deja de existir cuando no hay referencias a esa instancia y se ha ejecutado el finalizador de la instancia (si existe).

El valor inicial de una variable de instancia de una clase es el valor predeterminado (§5.2) del tipo de la variable.

A los efectos de una verificación de asignación definitiva, una variable de instancia se considera inicialmente asignada.

Es una limitación del comstackdor. El comstackdor intenta evitar que use una variable no asignada donde sea que pueda, lo cual es bueno ya que el uso de variables no inicializadas solía ser una fuente común de errores en el código C antiguo.

Sin embargo, el comstackdor no puede saber si la variable de instancia se inicializa antes de presionar esa llamada a un método porque podría establecerse con cualquier otro método, que puede ser llamado en cualquier orden por código externo.

El constructor implícito inicializa la variable de instancia para usted. Incluso cuando especifica un c’tor pero no inicializa un campo, lo hace como parte de la creación del objeto en el montón. Eso no es verdad para las variables locales de la stack.

En realidad, solo se trata de lo que la advertencia puede decirle. Realmente no hay forma de que la advertencia sea segura de que algún otro método no haya inicializado la variable de la clase, por lo que solo avisa sobre el que puede estar seguro de que no se ha inicializado.

Además, es una advertencia y no un error porque no hay nada técnicamente incorrecto con el uso de la variable no asignada (se garantiza que es ‘falso’), pero probablemente sea un error lógico que no se asigne.