initialize the data members in Constructor

I've been programming in C# and Java recently and I am curious what is the best place to initialize your classes fields?

Should you 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.

Replay

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).

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. 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.

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.

I think there is one caveat. I once committed such an error: Inside of a derived class, I "initialized at declaration" the fields inherited from an abstract base class. In that instance the polymorphism got really messed up, and the result was that there existed two sets of fields, one is "base" and another is the newly declared ones. The lesson was there is only one correct way to initialize fields in derived classes, which is to do it inside of the constructor.

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.

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.

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).

There is many various situations.

I need just empty list

It is clear. I just need to prepare my list and prevent exception when someone will add an item.

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

    public CsvFile()
    {
    }
}

I known the values

I exactly know what values I wanna 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 empty list by default with possible 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));
    }
}

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.

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.

Category: c# Time: 2008-08-23 Views: 0
Tags: java

Related post

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development

search

Front-end development

Database

development tools

Open Platform

Javascript development

.NET development

cloud computing

server

Copyright (C) avrocks.com, All Rights Reserved.

processed in 0.133 (s). 12 q(s)