Ordering of static fields in C# matters
I never thought ordering of relational static fields and properties in C# mattered. And, then, I started getting NREs on a property I know was set to a static-instance…
The setup
public static void Main()
{
Console.WriteLine(Person.Empty == null); // prints 'True'
}
public class Person
{
public static readonly Person Empty = empty;
private static readonly EmptyPerson empty = new EmptyPerson();
}
public sealed class EmptyPerson : Person { }
If you were to step-through the code, the first-time Person.Empty
is called, empty
is null
and gets returned as-is. Then, empty
is initialized. But, it’s too late since Empty
is static and will only get “initialized” once. But, if we swap the ordering…
public class Person
{
private static readonly EmptyPerson empty = new EmptyPerson();
public static readonly Person Empty = empty;
}
Now, empty
is an instance of EmptyPerson
when Empty
is called and everything is good.
Variations
The problem above is only a problem for static
fields/properties. If either were to be an expression-member, then ordering doesn’t matter:
public class Person
{
public static readonly Person Empty => empty;
private static readonly EmptyPerson empty = new EmptyPerson();
}
// This variation also works...
public class Person
{
public static readonly Person Empty = empty;
private static readonly EmptyPerson empty => new EmptyPerson();
}
Then, there’s the obvious…
public class Person
{
public static readonly Person Empty = new EmptyPerson();
}
But, I opted to use the private
member in several other spots within my code…
But, don’t do this!
Just as a final warning, don’t do this because while you have a getter
-only (i.e. readonly), you’ll also create a new instance of EmptyPerson
every time Empty
is called. 🤯
public class Person
{
// Don't do this!
public static Person Empty => new EmptyPerson();
}