Initialize class fields in constructor or at declaration?

429

I've been programming in C# and Java recently and I am curious where the best place is to initialize my class fields.

Should I do it at declaration?:

public class Dice
{
    private int topFace = 1;
    private Random myRand = new Random();

    public void Roll()
    {
       // ......
    }
}

or in a constructor?:

public class Dice
{
    private int topFace;
    private Random myRand;

    public Dice()
    {
        topFace = 1;
        myRand = new Random();
    }

    public void Roll()
    {
        // .....
    }
}

I'm really curious what some of you veterans think is the best practice. I want to be consistent and stick to one approach.

This question is tagged with java

~ Asked on 2008-08-23 19:59:42

15 Answers


320

My rules:

  1. Don't initialize with the default values in declaration (null, false, 0, 0.0…).
  2. Prefer initialization in declaration if you don't have a constructor parameter that changes the value of the field.
  3. If the value of the field changes because of a constructor parameter put the initialization in the constructors.
  4. Be consistent in your practice (the most important rule).

~ Answered on 2008-08-23 20:04:09


149

In C# it doesn't matter. The two code samples you give are utterly equivalent. In the first example the C# compiler (or is it the CLR?) will construct an empty constructor and initialise the variables as if they were in the constructor (there's a slight nuance to this that Jon Skeet explains in the comments below). If there is already a constructor then any initialisation "above" will be moved into the top of it.

In terms of best practice the former is less error prone than the latter as someone could easily add another constructor and forget to chain it.

~ Answered on 2008-08-24 16:04:02


16

I think there is one caveat. I once committed such an error: Inside of a derived class, I tried to "initialize at declaration" the fields inherited from an abstract base class. The result was that there existed two sets of fields, one is "base" and another is the newly declared ones, and it cost me quite some time to debug.

The lesson: to initialize inherited fields, you'd do it inside of the constructor.

~ Answered on 2013-11-10 22:56:45


16

The semantics of C# differs slightly from Java here. In C# assignment in declaration is performed before calling the superclass constructor. In Java it is done immediately after which allows 'this' to be used (particularly useful for anonymous inner classes), and means that the semantics of the two forms really do match.

If you can, make the fields final.

~ Answered on 2008-09-05 20:22:08


6

Assuming the type in your example, definitely prefer to initialize fields in the constructor. The exceptional cases are:

  • Fields in static classes/methods
  • Fields typed as static/final/et al

I always think of the field listing at the top of a class as the table of contents (what is contained herein, not how it is used), and the constructor as the introduction. Methods of course are chapters.

~ Answered on 2008-08-23 21:56:29


5

There are many and various situations.

I just need an empty list

The situation is clear. I just need to prepare my list and prevent an exception from being thrown when someone adds an item to the list.

public class CsvFile
{
    private List<CsvRow> lines = new List<CsvRow>();

    public CsvFile()
    {
    }
}

I know the values

I exactly know what values I want to have by default or I need to use some other logic.

public class AdminTeam
{
    private List<string> usernames;

    public AdminTeam()
    {
         usernames = new List<string>() {"usernameA", "usernameB"};
    }
}

or

public class AdminTeam
{
    private List<string> usernames;

    public AdminTeam()
    {
         usernames = GetDefaultUsers(2);
    }
}

Empty list with possible values

Sometimes I expect an empty list by default with a possibility of adding values through another constructor.

public class AdminTeam
{
    private List<string> usernames = new List<string>();

    public AdminTeam()
    {
    }

    public AdminTeam(List<string> admins)
    {
         admins.ForEach(x => usernames.Add(x));
    }
}

~ Answered on 2015-08-14 13:26:06


4

What if I told you, it depends?

I in general initialize everything and do it in a consistent way. Yes it's overly explicit but it's also a little easier to maintain.

If we are worried about performance, well then I initialize only what has to be done and place it in the areas it gives the most bang for the buck.

In a real time system, I question if I even need the variable or constant at all.

And in C++ I often do next to no initialization in either place and move it into an Init() function. Why? Well, in C++ if you're initializing something that can throw an exception during object construction you open yourself to memory leaks.

~ Answered on 2008-08-23 22:09:35


3

The design of C# suggests that inline initialization is preferred, or it wouldn't be in the language. Any time you can avoid a cross-reference between different places in the code, you're generally better off.

There is also the matter of consistency with static field initialization, which needs to be inline for best performance. The Framework Design Guidelines for Constructor Design say this:

? CONSIDER initializing static fields inline rather than explicitly using static constructors, because the runtime is able to optimize the performance of types that don’t have an explicitly defined static constructor.

"Consider" in this context means to do so unless there's a good reason not to. In the case of static initializer fields, a good reason would be if initialization is too complex to be coded inline.

~ Answered on 2017-05-14 05:46:59


3

In Java, an initializer with the declaration means the field is always initialized the same way, regardless of which constructor is used (if you have more than one) or the parameters of your constructors (if they have arguments), although a constructor might subsequently change the value (if it is not final). So using an initializer with a declaration suggests to a reader that the initialized value is the value that the field has in all cases, regardless of which constructor is used and regardless of the parameters passed to any constructor. Therefore use an initializer with the declaration only if, and always if, the value for all constructed objects is the same.

~ Answered on 2016-01-17 20:01:33


2

Consider the situation where you have more than one constructor. Will the initialization be different for the different constructors? If they will be the same, then why repeat for each constructor? This is in line with kokos statement, but may not be related to parameters. Let's say, for example, you want to keep a flag which shows how the object was created. Then that flag would be initialized differently for different constructors regardless of the constructor parameters. On the other hand, if you repeat the same initialization for each constructor you leave the possibility that you (unintentionally) change the initialization parameter in some of the constructors but not in others. So, the basic concept here is that common code should have a common location and not be potentially repeated in different locations. So I would say always put it in the declaration until you have a specific situation where that no longer works for you.

~ Answered on 2017-10-20 21:05:40


2

Being consistent is important, but this is the question to ask yourself: "Do I have a constructor for anything else?"

Typically, I am creating models for data transfers that the class itself does nothing except work as housing for variables.

In these scenarios, I usually don't have any methods or constructors. It would feel silly to me to create a constructor for the exclusive purpose of initializing my lists, especially since I can initialize them in-line with the declaration.

So as many others have said, it depends on your usage. Keep it simple, and don't make anything extra that you don't have to.

~ Answered on 2017-05-24 20:27:19


1

There is a slight performance benefit to setting the value in the declaration. If you set it in the constructor it is actually being set twice (first to the default value, then reset in the ctor).

~ Answered on 2008-08-29 15:47:24


0

Not a direct answer to your question about the best practice but an important and related refresher point is that in the case of a generic class definition, either leave it on compiler to initialize with default values or we have to use a special method to initialize fields to their default values (if that is absolute necessary for code readability).

class MyGeneric<T>
{
    T data;
    //T data = ""; // <-- ERROR
    //T data = 0; // <-- ERROR
    //T data = null; // <-- ERROR        

    public MyGeneric()
    {
        // All of the above errors would be errors here in constructor as well
    }
}

And the special method to initialize a generic field to its default value is the following:

class MyGeneric<T>
{
    T data = default(T);

    public MyGeneric()
    {           
        // The same method can be used here in constructor
    }
}

~ Answered on 2018-07-08 12:32:06


0

When you don't need some logic or error handling:

  • Initialize class fields at declaration

When you need some logic or error handling:

  • Initialize class fields in constructor

This works well when the initialization value is available and the initialization can be put on one line. However, this form of initialization has limitations because of its simplicity. If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate. Instance variables can be initialized in constructors, where error handling or other logic can be used.

From https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html .

~ Answered on 2020-04-20 10:23:14


0

I normally try the constructor to do nothing but getting the dependencies and initializing the related instance members with them. This will make you life easier if you want to unit test your classes.

If the value you are going to assign to an instance variable does not get influenced by any of the parameters you are going to pass to you constructor then assign it at declaration time.

~ Answered on 2008-08-24 15:59:11


Most Viewed Questions: