I'm getting a TypeInitializationException when running this C# code.
It happens when a constructor tries to add an instance to a static list that should already be initialized.
You can run it here:
https://www.programiz.com/online-compiler/7Z2b1vggBclrq
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Console.WriteLine("Hello");
Base baseClass = Base.getElement("test1");
}
}
public class Derived : Base
{
public static Derived derived_1 = new Derived("test1");
public static Derived derived_2 = new Derived("test2");
public static Derived derived_3 = new Derived("test3");
public static Derived derived_4 = new Derived("test4");
protected Derived(string field1) : base(field1)
{
}
}
public class Base
{
public static List<Base> list;
public static Base[] derivedClass;
static Base()
{
list = new List<Base>();
derivedClass = new Base[]
{
Derived.derived_1,
Derived.derived_2,
Derived.derived_3,
Derived.derived_4
};
}
public string field1;
protected Base(string field1)
{
this.field1 = field1;
list.Add(this); // list is null here
}
public static Base getElement(string field1)
{
foreach (var element in list)
{
if (element.field1.Equals(field1))
{
return element;
}
}
return null;
}
}
Output
ERROR!
Unhandled Exception:
System.TypeInitializationException: The type initializer for 'Base' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Derived' threw an exception. ---> System.NullReferenceException: Object reference not set to an instance of an object
at Base..ctor (System.String field1) [0x0000f] in <db66da3dae244ddc8dabed6518753b54>:0
at Derived..ctor (System.String field1) [0x00000] in <db66da3dae244ddc8dabed6518753b54>:0
at Derived..cctor () [0x00000] in <db66da3dae244ddc8dabed6518753b54>:0
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at Program.Main () [0x0000c] in <db66da3dae244ddc8dabed6518753b54>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: The type initializer for 'Base' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Derived' threw an exception. ---> System.NullReferenceException: Object reference not set to an instance of an object
at Base..ctor (System.String field1) [0x0000f] in <db66da3dae244ddc8dabed6518753b54>:0
at Derived..ctor (System.String field1) [0x00000] in <db66da3dae244ddc8dabed6518753b54>:0
at Derived..cctor () [0x00000] in <db66da3dae244ddc8dabed6518753b54>:0
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at Program.Main () [0x0000c] in <db66da3dae244ddc8dabed6518753b54>:0
The confusing part is that the static fields (list and derivedClass) are clearly initialized in the static constructor, yet when list.Add(this) runs inside the base constructor, list is still null.
For context: this same pattern works in Java, but in C# it throws during static initialization.
Question: Why does this throw a TypeInitializationException even though the static fields are initialized?
Derivedtype initializer is executed, because there's no static constructor. See codeblog.jonskeet.uk/2010/01/26/… for an example of how this has changed over time. Fundamentally: don't do this sort of thing, it's too hard to reason about and get right. (If you must do something like this, use static constructors to make the timing easier to reason about.)ToStringif you want to see "field1" as output).