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?
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:
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
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With