The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Initializing in class body instead of constructor

I just wanted to get others' opinions on initializing members where they are declared instead of in a constructor in C# code.  I guess it's a style question, but if there are any technical gotchas here I'd like to know.

For example:

public class Foo
{
  string bar = "bat";

  public Foo()
  {}
}

VS:

public class Foo
{
  string bar;
 
  public Foo()
  {
    bar = "bat";
  }
}
John Cromartie Send private email
Monday, August 13, 2007
 
 
If you initialze them where declared then they're initialized earlier: for example in the following, when you construct a Foo instance, foo1 is initialized before the Bar constructor is invoked, and foo2 is initialized after.

public class Bar
{
  public Bar()
  {}
}

public class Foo
{
  string foo1 = "bat";
  string foo2;

  public Foo()
  {
    foo2 = "bip";
  }
}
Christopher Wells Send private email
Monday, August 13, 2007
 
 
public class Bar
{
  public Bar()
  {}
}

public class Foo : Bar
{
  string foo1 = "bat";
  string foo2;

  public Foo()
  {
    //Bar constructor is implicitly called before this next statement
    foo2 = "bip";
  }
}
Christopher Wells Send private email
Monday, August 13, 2007
 
 
Amazing depth in the Foo:Bar example, Christopher. Hats off.

Not sure if there is more than "very few" scenarios where this difference is actually important. It seems like taking advantage of early initialization feature can be used to compensate for somewhat incomplete class design, but in regular situations it will be just a "style question".
DK Send private email
Monday, August 13, 2007
 
 
That's good to know.  Just to make sure I have this straight, the order of initialization for members is:

1. initialized in class body
2. base constructor
3. constructor
John Cromartie Send private email
Monday, August 13, 2007
 
 
Yes, that's what I remember. An easy way to verify this is to build the example, and use a debugger to step through (line by line) the construction of an instance.
Christopher Wells Send private email
Monday, August 13, 2007
 
 
Another time it can makes a slight difference is if you have an overloaded constructor (in which case if it's not initialized in the class then it may need to be initialized in both constructors).

I prefer to initialize where declared, except when initializing to a value that's passed into the constructor as a parameter.
Christopher Wells Send private email
Monday, August 13, 2007
 
 
This can also be important when the class hierarchy is being serialized.
xampl Send private email
Monday, August 13, 2007
 
 
Well, the first form (initializing bar when it is declared) is not allowed in C++. The second for is (initializing bar in the constructor body) is also not a good idea, because you are doing extra work (by forcing string to be default constructed and then initializing over the default construction). The proper way to do this is with a member initialization list:

Foo.h:
  #include <string>
  using namespace std;

  class Foo
  {
      string bar;
      Foo();
      ~Foo();
  }

Foo.cpp:
  #include <Foo.h>

  Foo::Foo() : bar("bat")
  {
  }

  Foo::~Foo()
  {
  }

In general, the only types of members that can be initialized when they are declared are static members of built-in (non-object) types (char, int, float, ...). Anything else should be initialiazed in the member initialization list.

You can move the member initialzation list into the header file so that the initialization is closer to the declaration:

Foo.h:
  #include <string>
  using namespace std;

  class Foo
  {
      string bar;
      Foo() : bar("bat") {}
      ~Foo() {}
  }

I think your placement of the keyword "public" is also a mistake. C++ is not a simple language, there are some things that a C or Java programmer would think were legal but aren't, and even more things that are legal but are a Very Bad Idea[TM]. I'd suggest you get a copy of "Effective C++" by Scott Meyers and read it carefully.
Jeffrey Dutky Send private email
Monday, August 13, 2007
 
 
If bar is always going to be "bat" you could use a static constructor. That way it never gets called again.

Declaring and assigning in constructor is more work than just assigning. Ditto in the declaration section.

Per Jeff Richters book - Declare separately and the assign in the constructor is cheaper. I tend to do this.
struct
Monday, August 13, 2007
 
 
Jeff, the OP specifically asked about C#, so the comments on C++ aren't really germaine to the topic.

As for the actual question, I tend towards initialization in the constructor, but I can't really say why. I guess I like having all my initializations in one place rather than scattered, but that's a pretty poor reason.
Chris Tavares Send private email
Monday, August 13, 2007
 
 
I prefer to initialize in the declaration whenever possible.  The reason is simple.  When you initialize in the constructor, you have to initialize in every constructor.  When you initialize in the declaration, the initialization occurs regardless of constructor.  Here's an example to demonstrate what I mean:

class TestClass
{
  string abc = "abc";
  string def;

  public TestClass()
  {
    def = "def";
  }

  public TestClass(int i)
  {
  }
}

When new TestClass() is called, abc and def will both be properly initialized.  When new TestClass(0) is called, abc is properly initialized but def is left as null.  In "real world" situations, it's not difficult to introduce bugs by adding a new constructor missing some initializations when code isn't as simple or clear as this example. 

When you initialize in the constructor and have multiple constructors, you end up either having to repeat the initialization in every constructor or moving the intialization to some separate Init() method that has to be called in every constructor.  I think it's clearer and more straightforward to just eliminate this confusion by initializing in the declaration since this is the only code path that's guaranteed to be called.
SomeBody Send private email
Monday, August 13, 2007
 
 
Oops, sorry, I didn't see the mention of C#, I need to slow down. Please disregard and carry on.
Jeffrey Dutky Send private email
Tuesday, August 14, 2007
 
 
I have done the following to have a helper class handle some aspect of the code.  It fails in C# with "Keyword 'this' is not available in the current context
" (but works in Java).

    public class Bar
    {
        public Bar(Foo theFoo)
        {
          // do something later on with theFoo
        }
    }

    public class Foo
    {
        string foo1 = "bat";
        string foo2;

        // Bar handles something for Foo
        Bar b = new Bar(this);

        public Foo()
        {
            //Bar constructor is implicitly called before this next statement
            foo2 = "bip";
        }
    }
Kenneth Brittain Send private email
Tuesday, August 14, 2007
 
 
Static initializers are also thread safe (at least in Java).
OneMist8k
Tuesday, August 14, 2007
 
 
I prefer initializing values at declaration if possible for this type of scenario as someoone else said:

Public Class Person
{
    private int myInt;

    public Person()
    { myInt = 10;}
}

Public Class Employee : Person
{
  public Employee() : base()
  {}
}

The gotcha that I encountered is forgetting to call the base constructor . A lot of times I don't want to because of various logic.  Putting the value in the declaration I don't have to worry about this.

My Preference :

Public Class Person
{
    private int myInt = 10;

    public Person()
    {}
}

Public Class Employee : Person
{
  public Employee()
  {}
}
Ben Dempsey Send private email
Friday, August 24, 2007
 
 
this is just personal style, but i prefer to always initialize in the constructor unless there is a good reason not too.  Constants, initializing a logger class, might be 2 such instances.  reason for this is that class members can be declared at the bottom(i would also call that poor style, but thats another issue) of the class instead of the top, and keeping everything in the constructor keeps initializations all in one place.
Sean
Thursday, August 30, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz