Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing Constructor set fields and Field Initializers [closed]

Tags:

c#

oop

When designing a class, are there any guidelines regarding initializing class fields? There are two separate methods of initialization. I can use either inline field initializers, or I can initialize them in the constructors. It becomes even more... interesting, when static fields are introduced as then the fields can be initalized when defined, in the static constructor, or in the instance constructor with a check to see if the field has been set already. This becomes even more confusing when factories are introduced.

Example 1 - Inline Initilization


    public class ExampleOne
    {
        private readonly IDictionary _collection = new Dictionary();

        ...
    }       

Example 2 - Constructor Initialization


    public class ExampleTwo
    {
        private readonly IDictionary _collection;

        public ExampleTwo() 
        {
            _collection = new Dictionary();
        }
        ...
    }       

Example 3 - Static Inline Initialization


    public class ExampleThree
    {
        private static readonly IDictionary __collection = new Dictionary();

        ...
    }       

Example 4 - Static Constructor Initialization


    public class ExampleFour
    {
        private static IDictionary __collection;

        static ExampleFour() 
        {
            _collection = new Dictionary();
        }

        ...
    }       

Example 5 - Static/Instance Constructor Mix Initialization


    public class ExampleFive
    {
        private static readonly IDictionary __collection;
        private static IDictionary __anotherCollection;

        static ExampleFive() 
        {
            _collection = new Dictionary();
        }

        public ExampleFive()
        {
           if( __anotherCollection == null ) 
           {
            __anotherCollection = new Dictionary();
           }
        }

        ...
    }       

Example 6 - Factory Methods


    public class ExampleSix
    {
        private static readonly IDictionary __collection;
        private static IDictionary __anotherCollection;

        static ExampleSix() 
        {
            _collection = new Dictionary();
        }

        public static ExampleSix Create()
        {
           if( __anotherCollection == null ) 
           {
            __anotherCollection = new Dictionary();
           }

           var example = new ExampleSix();
           return example;
        }

        ...
    }       

Currently the classes that I have tend to mix all of these. Although I have tried to avoid setting static fields in the instance constructors.

Example 7 - Mixed


    public class ExampleSeven
    {
        private static readonly IDictionary __collection = new Dictionary();
        private static readonly IDictionary __anotherCollection;
        private static readonly IDictionary __thirdCollection;
        private static IDictionary __fourthCollection;

        static ExampleSeven() 
        {
            __anotherCollection = new Dictionary();
        }

        public ExampleSeven() 
        {
            if( __thirdCollection == null )
            {
               __thirdCollection = new Dictionary();
            }
        }

        public static ExampleSeven Create()
        {
           if( __fourthCollection == null ) 
           {
            __fourthCollection = new Dictionary();
           }

           var example = new ExampleSeven();
           return example;
        }

        ...
    }       

I am more concerned, as can be seen in the examples, with fields that are class objects instead of simple primitives. I understand that initializing the fields when they are declared will mark the class as beforeinit, and the fact that I cannot pass this into fields that are initialized when declared. My concern is primarily in cases similar to above seven examples. Am I setting myself up for any kind of unforeseen issues by mixing them this way?

like image 232
David Williams Avatar asked Aug 16 '26 15:08

David Williams


1 Answers

Usually it doesn't really matter whether you initialize fields in the constructor or using field initializers. However, there are a few subtleties that you should be aware of regarding the timing and order of operations:

  • Instance field initializers and instance constructors run in the following order, which may be surprising:

    • derived class field initializers
    • base class field initializers
    • base class constructor
    • derived class constructor

See this article by Eric Lippert for a discussion on the reasons of this behavior: http://blogs.msdn.com/b/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx

  • The presence of a static constructor in a class introduces subtle changes in the way the type is initialized. I won't go into the details here, but Jon Skeet has a very thorough article about it: http://csharpindepth.com/Articles/General/Beforefieldinit.aspx

To answer your question, there is no definite rule about where you should initialize the fields. Sometimes it is more natural to initialize the field "inline" if the initialization is short, but if it's long it should probably be in the constructor. Sometimes fields have to be initialized in the constructor, because field initializers can't contain a reference to this. I often have a mix of both styles in my code, and so far I didn't run into issues because of this. Just keep in mind the order of execution mentioned above...

like image 191
Thomas Levesque Avatar answered Aug 18 '26 06:08

Thomas Levesque



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!