Should we always include a default constructor in the class?
Asked Answered
V

8

83

I have been asked this question by a colleague that should we always include a default constructor in a class? If so, why? If no, why not?

Example

public class Foo {

    Foo() { }

    Foo(int x, int y) {
        ...
    } 

}

I am also interested to get some lights on this from experts.

Vancouver answered 11/9, 2010 at 18:2 Comment(1)
As usual - only when it's necessary.Bowie
N
133

You have to keep in mind that if you don't provide an overloaded constructor, the compiler will generate a default constructor for you. That means, if you just have

public class Foo
{ 
} 

The compiler will generate this as:

public class Foo
{ 
    public Foo() { }  
} 

However, as soon as you add the other constructor

public class Foo
{ 
    public Foo(int x, int y)
    { 
        // ... 
    }  
} 

The compiler will no longer automatically generate the default constructor for you. If the class was already being used in other code which relied on the presence of a default constructor, Foo f = new Foo();, that code would now break.

If you don't want someone to be able to initialize the class without providing data you should create a default constructor which is private to be explicit about the fact that you are preventing instances from being constructed with no input data.

There are times, however, when it is necessary to provide a default constructor (whether public or private). As was previously mentioned, some types of serialization require a default constructor. There are also times when a class has multiple parameterized constructors but also requires "lower level" initialization, in which case a private default constructor can be used which is chained in from the parameterized constructors.

public class Foo
{
   private Foo()
   {
      // do some low level initialization here
   }

   public Foo(int x, int y)
      : this()
   {
      // ...
   }

   public Foo(int x, int y, int z)
      : this()
   {
      // ...
   }
}
Nosing answered 11/9, 2010 at 18:12 Comment(5)
You also shouldn't have () after the class name. Take them out and you've enough code that you can try to compile it and see that this answer is wrong, and attempting to use the default constructor will result in "'Foo' does not contain a constructor that takes '0' arguments".Restoration
@Jon Hanna: Fixed the () after the class names. However, your comment about the answer being wrong is...well, wrong. The first code will compile and allow you to write code such as Foo f = new Foo();. However, as soon as you change the class to that shown in the third example, Foo f = new Foo(); will cause a compiler error - which was my point. As long as you have no constructors, the compiler adds the default constructor for you. As soon as you add any other constructor, the compiler no longer adds the default constructor and code which relied on it being present breaks.Nosing
+1 this. Creating empty default constructors is annoying IMO, and tools like ReSharper just mark it as dead code.Gates
@Scott. Yes, just a mis-read from scanning too quickly. My bad.Restoration
@ScottDorman there's a pending edit with change: public Foo() { }` >>> public Foo() : base() { } and message The generated constructor also calls the base default constructor, important to know when considering inheritance (mdsn source). Whether it gets approved or not, please check.Mcpeak
E
21

Some things (like serialisation) require a default constructor. Outside of that, however, a default constructor should only be added if it makes sense.

For example, if the Foo.X and Foo.Y properties are immutable after construction then a default constructor doesn't really make sense. Even if it were to used for an 'empty' Foo, a static Empty accessor would be more discoverable.

Ectomorph answered 11/9, 2010 at 18:6 Comment(1)
Serialisation does not require a default constructor. If you have a class you want to be serialisable, for which a default constructor does not make sense, then implement ISerializable, and add a constructor (private if sealed, protected otherwise) with the signature ClassName(SerializationInfo info, StreamingContext context) that mirrors the implementation of ISerializable.GetObjectData.Restoration
B
11

I would say no, definitely not always. Suppose you have a class with some readonly fields that must be initialized to some value, and there are no reasonable defaults (or you don't want there to be)? In this scenario I don't think a parameterless constructor makes sense.

Binky answered 11/9, 2010 at 18:7 Comment(1)
Totally agree. Classes should always be instantiated in a valid state. If you have a default ctor and set properties post-construction, when is the instance valid? After settings some properties? After setting all? Who knows.Hovercraft
R
6

Having a default constructor is only a good idea if it makes sense to have such an object.

If you produce an object which is not in a valid state from such a constructor, then the only thing it can do is introduce a bug.

Restoration answered 11/9, 2010 at 22:18 Comment(0)
T
3

As a side note, when using struct instead of class, note that there are no way to leave the default constructor out, nor is it possible to define it yourself, so regardless of which constructors you define, make sure that the default state of the struct (when all variables are set to their default state (usually 0 for value types, and null for reference types) won't break your implementation of the struct.

Thaumatology answered 12/9, 2010 at 5:58 Comment(0)
A
0

In most cases a default constructor is a good idea. But since you use the word "always", all that's needed is one counterexample. If you look at the Framework, you'll find plenty. For example, System.Web.HttpContext.

Arther answered 11/9, 2010 at 18:10 Comment(0)
A
0

Yes It is better to have a default constructor in place to ensure you avoid any confusion. I have seen people just do nothing inside a default constructor (even in Microsoft's own classes) but still like to keep it as objects do get default(type) automatically. The classes which does not specify default constructor, .NET will automatically add them for you.

Serialization needs Default constructor if you use existing serializers as it makes sense for general purpose serializers, otherwise you need to create your own implementation.

Attenuant answered 11/9, 2010 at 20:35 Comment(2)
Serialisation does not require a default constructor. If you have a class you want to be serialisable, for which a default constructor does not make sense, then implement ISerializable, and add a constructor (private if sealed, protected otherwise) with the signature ClassName(SerializationInfo info, StreamingContext context) that mirrors the implementation of ISerializable.GetObjectData.Restoration
Point counted. Actually I know it, but in general people do want to be simple. But you added a point to the answer. Thanks.Attenuant
U
0

A generic type can only be instantiated with C# means (without reflection) if it has a default constructor. Also, the new() generic type constraint has to be specified:

void Construct<T>()
    where T : new()
{
    var t = new T();
    ...
}

Calling this method using a type as generic type argument that has no default constructor results in a compiler error.

Unmusical answered 10/3, 2016 at 19:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.