bryanjonker
bryanjonker

Reputation: 3416

Changing order that private readonly properties are evaluated

If you have the following:

 public class MyClass {
      private static readonly MyObject obj = 
              new MyObject { parent = listObject[0] };
      private static readonly List<MyObject> listObject = 
              new List<MyObject> { new MyObject() };
 }

It will throw a run-time error when MyClass is initialized because when it attempts to initialize obj, listObject is null.

Edit: Is there a way to explicitly specify when each readonly object is initialized (like through an attribute) so listObject is initialized before obj (other than refactoring or reordering the code)? I realize the order determines when each item gets executed, but having the order determine that seems brittle.

I apologize in advance for the simplistic code.

Upvotes: 2

Views: 193

Answers (4)

User 12345678
User 12345678

Reputation: 7804

public class MyClass {
    private static readonly MyObject obj;
    private static readonly List<MyObject> listObject;

    static MyClass()
    {
        listObject = new List<MyObject> { new MyObject() };
        obj = new MyObject { parent = listObject[0] };
    }
}

You can re-arrange the order the fields are initialized if you bring the initialization into the constructor.

The initialization of member and static variables are guaranteed to occur in the order they appear in the file. So you could avoid the compile-time error by initializing the list first:

static readonly List<MyObject> listObject = new List<MyObject> { new MyObject() };
static readonly MyObject obj = new MyObject { parent = listObject[0] };

I would opt for initializing your fields in the constructor still. Relying on the fields to be initialized in the order they are declared is quite brittle. What if somebody changes the order of the fields to please their aesthetic want? Boom.

Upvotes: 4

Cemafor
Cemafor

Reputation: 1653

You need a static constructor!!

public class MyClass {
    private static readonly MyObject obj;
    private static readonly List<MyObject> listObject;

    static MyClass()
    {
        listObject = new List<MyObject> { new MyObject() };
        obj = new MyObject { parent = listObject[0] };
    }
}

"A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced."

Upvotes: 2

Marc Gravell
Marc Gravell

Reputation: 1063609

Field initializers are explicitly executed in code order - i.e. top down. Note that this is still undefined if using partial classes in separate files.

But: if the order matters, then you should move the code into the constructor (a static constructor in this case). Reordering interdependent field initializers is just asking for trouble during maintenance.

Upvotes: 1

alex
alex

Reputation: 12654

The order of static fields is important. They are initialized from top to bottom, and you can rearrange them to fix your problem.

 public class MyClass { 
     private static readonly List<MyObject> listObject = 
              new List<MyObject> { new MyObject() };
     private static readonly MyObject obj = 
              new MyObject { parent = listObject[0] };
 }

But this can introduce unexpected problems, for example when code formatter sorts field definition alphabetically.

Upvotes: 1

Related Questions