Para deducir el orden en que se
inicializarán las variables de un tipo de dato basta saber cuál es el momento
en que se inicializa cada una y cuando se llama a los constructores:
- Los campos
estáticos sólo se inicializan
la primera vez que se accede al tipo al que pertenecen, pero no en
sucesivos accesos. Estos accesos pueden ser tanto para crear objetos de
dicho tipo como para acceder a sus miembros estáticos. La inicialización
se hace de modo que en primer lugar se dé a cada variable el valor por
defecto correspondiente a su tipo, luego se dé a cada una el valor inicial
especificado al definirlas, y por último se llame al constructor del tipo.
Un constructor de tipo es similar a un constructor normal sólo que en su
código únicamente puede accederse a miembros static
(se verá en el Tema 8: Métodos)
- Los campos
no estáticos se inicializan cada vez que se crea un objeto del tipo de
dato al que pertenecen. La inicialización se hace del mismo modo que en el
caso de los campos estáticos, y una vez terminada se pasa a ejecutar el
código del constructor especificado al crear el objeto. En caso de que la
creación del objeto sea el primer acceso que se haga al tipo de dato del
mismo, entonces primero se inicializarán los campos estáticos y luego los
no estáticos.
- Los parámetros
se inicializan en cada llamada al método al que pertenecen con los valores
especificados al llamarlo.
- Las variables
locales se inicializan en cada llamada al método al cual pertenecen
pero tras haberse inicializado los parámetros definidos para el mismo. Si
no se les da valor inicial no toman ninguno por defecto, considerándose
erróneo todo acceso de lectura que se haga a las mismas mientras no se les
escriba algún valor.
Hay que tener en cuenta que al
definirse campos estáticos pueden hacerse definiciones cíclicas en las que el
valor de unos campos dependa del de otros y el valor de los segundos dependa
del de los primeros. Por ejemplo:
class
ReferenciasCruzadas
{
static int a = b +
1;
static int b = a + 1;
public static void
Main()
{
System.Console.WriteLine("a
= {0}, b = {1}", a, b);
}
}
Esto sólo es posible hacerlo al
definir campos estáticos y no entre campos no estáticas o variables locales, ya
que no se puede inicializar campos no estáticos en función del valor de otros
miembros no estáticos del mismo objeto porque el objeto aún no estaría incializados,
y no se puede inicializar variables locales en función del valor de otras
variables locales definidas más adelante porque no se pueden leer variables no
inicializadas. Además, aunque las constantes sean implícitamente estáticas
tampoco puede hacerse definiciones cíclicas entre constantes.
En primer lugar, hay que señalar
que escribir un código como el del ejemplo anterior no es un buen hábito de
programación ya que dificulta innecesariamente la legibilidad del programa. Aún
así, C# admite este tipo de códigos y para determinar el valor con que se
inicializarán basta tener en cuenta que siempre se inicializan primero todos
los campos con sus valores por defecto y luego se inicializan aquellos que
tengan valores iniciales con dichos valores iniciales y en el mismo orden en
que aparezcan en el código fuente. De este modo, la salida del programa de
ejemplo anterior será:
a = 1, b = 2
Nótese que lo que se ha hecho es
inicializar primero a y b con sus valores por defecto (0 en este caso), luego
calcular el valor final de a y
luego calcular el valor final de b. Como
b vale 0 cuando se calcula el
valor final de a, entonces el
valor final de a es 1; y como
a vale 1 cuando se calcula el
valor final de b, entonces el
valor final de b es 2.