uso una objeto new metodos instanciar inicializar ejemplos diccionarios crear como clases clase anidados c# static dependencies internals

una - new dictionary c#



Orden de constructores/inicializadores estáticos en C# (4)

Personalmente, me deshace de los inicializadores estáticos ya que no está claro y agrego un constructor estático para inicializar estas variables.

static private List<int> a; static private List<int> b; static SomeClass() { a = new List<int>() { 0 }; b = new List<int>() { a[0] }; }

Entonces no tienes que adivinar qué está pasando y estás siendo claro en tus intenciones.

Mientras trabajaba en una aplicación de C #, me di cuenta de que en varios lugares los inicializadores estáticos tienen dependencias entre sí de esta manera:

static private List<int> a = new List<int>() { 0 }; static private List<int> b = new List<int>() { a[0] };

Sin hacer nada especial que funcionó. ¿Eso es solo suerte? ¿Tiene C # reglas para resolver esto?

Editar: (re: Panos) En un archivo, el orden léxico parece ser el rey. ¿Qué pasa con los archivos?

Al mirar probé una dependencia cíclica como esta:

static private List<int> a = new List<int>() { b[0] }; static private List<int> b = new List<int>() { a[0] };

y el programa no funcionó igual (el palo de prueba falló en todos los ámbitos y no miré más allá).


Sí, tuviste suerte. C # parece ejecutar el código en el orden en que aparece en la clase.

static private List<int> a = new List<int>() { 0 }; static private List<int> b = new List<int>() { a[0] };

Funcionará pero ...

static private List<int> b = new List<int>() { a[0] }; static private List<int> a = new List<int>() { 0 };

Fallará.

Yo recomendaría poner todas sus dependencias en un solo lugar, el constructor estático es el lugar para esto.

static MyClass() { a = new List<int>() { 0 }; b = new List<int>() { a[0] }; }


Vea la sección 10.4 de la especificación de C # para las reglas aquí:

cuando se inicializa una clase, todos los campos estáticos en esa clase se inicializan primero a sus valores predeterminados, y luego los inicializadores de campo estáticos se ejecutan en orden textual. Del mismo modo, cuando se crea una instancia de una clase, todos los campos de instancia en esa instancia se inicializan primero a sus valores predeterminados, y luego los inicializadores del campo de instancia se ejecutan en orden textual. Es posible que se observen campos estáticos con inicializadores variables en su estado de valor predeterminado. Sin embargo, esto se desaconseja fuertemente como una cuestión de estilo.

Entonces, en otras palabras, en su ejemplo, ''b'' se inicializa a su estado predeterminado (nulo) y, por lo tanto, la referencia a él en el inicializador de ''a'' es legal, pero daría como resultado una NullReferenceException.

Estas reglas son diferentes a las de Java (consulte la sección 8.3.2.3 de las reglas de JLS para Java sobre referencias directas , que son más restrictivas).


Parece depender de la secuencia de líneas. Este código funciona:

static private List<int> a = new List<int>() { 1 }; static private List<int> b = new List<int>() { a[0] };

mientras que este código no funciona (arroja una NullReferenceException )

static private List<int> a = new List<int>() { b[0] }; static private List<int> b = new List<int>() { 1 };

Entonces, obviamente no existen reglas para la dependencia cíclica. Sin embargo, es peculiar que el compilador no se queje ...

EDITAR - ¿Qué está pasando "a través de los archivos"? Si declaramos estas dos clases:

public class A { public static List<int> a = new List<int>() { B.b[0] }; } public class B { public static List<int> b = new List<int>() { A.a[0] }; }

e intenta acceder a ellos con este código:

try { Console.WriteLine(B.b); } catch (Exception e) { Console.WriteLine(e.InnerException.Message.); } try { Console.WriteLine(A.a); } catch (Exception e) { Console.WriteLine(e.InnerException.Message); } try { Console.WriteLine(B.b); } catch (Exception e) { Console.WriteLine(e.InnerException.Message); }

estamos obteniendo esta salida:

The type initializer for ''A'' threw an exception. Object reference not set to an instance of an object. The type initializer for ''A'' threw an exception.

Por lo tanto, la inicialización de B causa una excepción en el constructor estático A y el campo izquierdo a con el valor predeterminado (nulo). Como a es null , b tampoco se puede inicializar correctamente.

Si no tenemos dependencias cíclicas, todo funciona bien.

EDITAR: en caso de que no hayas leído los comentarios, Jon Skeet ofrece una lectura muy interesante: las diferencias entre los constructores estáticos y los inicializadores de tipo .