9

I worked with a developer that had many years my senior in C# experience. I no longer have a way to contact him and I remember him saying that it's not a good idea to include code in a default parameter less constructor but I cannot remember the reason why.

Is it good practice or bad practice to include code in the default constructor in C# or any language for that matter?

Atif
  • 942
  • 1
  • 6
  • 19
broguyman
  • 1,386
  • 4
  • 19
  • 36

9 Answers9

8

It depends on the situation, but it is definitely NOT bad practice to put code in default constructors. If you need to, go ahead and do it.

Jeff
  • 972
  • 5
  • 11
6

That depends on the situation, sometimes it's needed, sometimes it can be used, sometimes it should not be there.

What's important is that any constructor should leave the object in a properly initialised state. If an object always needs some code for initialising, but no specific input to do that, a parameterless constructor would be a good place for that.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Of significant importance, the constructor must not throw exceptions. If any piece of the initialization may throw, wrap in a try/catch and handle it. – GalacticCowboy Apr 26 '13 at 18:53
  • @GalacticCowboy: On the contrary, if the constructor is incapable of initialising the object properly, it *should* throw an exception. That is the only way that the constructor can keep the object from being created. See for example: http://stackoverflow.com/questions/3629849/throwing-argumentnullexception-in-constructor – Guffa Apr 26 '13 at 19:51
  • Ah, true enough. I was basing this on my memory of an FxCop rule, but it actually throws on *static* constructors - an exception in a static constructor would result in the type being broken for the entire app-domain. – GalacticCowboy Apr 26 '13 at 20:25
  • @GalacticCowboy: Ah, that makes sense. That would be an uncatchable exception. :) – Guffa Apr 26 '13 at 20:51
5

What comes to mind is Item 17 from Effective Java (by Joshua Bloch):

Item 17: Design and document for inheritance or else prohibit it

He explains that a constructor should not invoke methods that are overridable:

public class Super {
    // Broken - constructor invokes an overridable method
    public Super() {
        overrideMe();
    }
    public void overrideMe() {
    }
}

What ends up happening is that you are invoking the superclass's constructor (when you create an instance of the subclass) and you get unexpected behavior.

If your constructor does invoke other methods in the class, you need to document this in your API so when developers subclass it they will know what to expect.

Otherwise, there's no harm from putting code in your constructor.

Atif
  • 942
  • 1
  • 6
  • 19
  • its true https://msdn.microsoft.com/en-us/library/vstudio/ms229060(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1 – siamak Mar 31 '15 at 23:20
2

Since your are using C# with the .NET framework. Let me give you the complete "Constructor Design" article by MSDN:

http://msdn.microsoft.com/en-us/library/vstudio/ms229060(v=vs.100).aspx

In my opinion you should put just initialization code inside your constructor.

gustavodidomenico
  • 4,640
  • 1
  • 34
  • 50
2

When you deserialize an object with a BinaryFormatter, the default constructor is not run when the object is created. The BinaryFormatter uses a trick to get .NET to give an initialized instance in which no default constructors is run.

This shouldn't pose a problem, because the BinaryFormatter fills in all the private members itself. The only situation that I can imagine being dangerous is if you use the default constructor to "register" the object somewhere in some other static class or something along those lines, in which case you've got a whole new set of problems.

Dave Van den Eynde
  • 17,020
  • 7
  • 59
  • 90
  • That shouldn't be a problem, as you simply can keep from marking the class as serializable if it can't be created by deserialisation. – Guffa Apr 26 '13 at 19:59
  • @Guffa that's not the issue here. You might not know that this sort of thing happens when deserialization. Also, you can implement the IDeserializationCallback interface to get in on this event if you really need it. But you need to know. – Dave Van den Eynde Apr 27 '13 at 14:32
2

Rule of Thumb

Make it as simple as possible.

The whole point of good coding standards is for maintainability and debug-ability. We've all come across code that is spaghetti. This is just so others understand your API better. Even with good javadoc, most people don't expect the constructor to change the application state.

For example, if instantiating your object does some database manipulation, you better have a damn good reason.

Counter Example

You still need to do what is best. If you decide to have a lazy-loaded singleton that loads a cache or connection or what have you, the whole point is that it will automatically load something when you instantiate it.

Daniel Moses
  • 5,872
  • 26
  • 39
0

I know we put a call to the initialization to all parameters in the default constructor. There are times when we need to "blank" the data outside of just the declaration, so we do it in a separate method and call it at the lowest constructor for any object.

krillgar
  • 12,596
  • 6
  • 50
  • 86
0

It's a matter of taste. I find these rules defined by user kokos very helpful:

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

see: Initialize class fields in constructor or at declaration?

Community
  • 1
  • 1
MUG4N
  • 19,377
  • 11
  • 56
  • 83
0

Uinitialized class fields usually should end up in the default constructor. If you initialize class fields on the same line as the declarations, those statements will not run if you deserialize such an object. Besides it's good practice to collect all initalizations in the default ctor.

David S.
  • 5,965
  • 2
  • 40
  • 77