Constructor Usage Guidelines

The following rules outline the usage guidelines for constructors:

  • Provide a default private constructor if there are only static methods and properties on a class. In the following example, the private constructor prevents the class from being created.

    NotInheritable Public Class Environment
       ' Private constructor prevents the class from being created.
       Private Sub New()
          ' Code for the constructor goes here.
       End Sub
    End Class
    [C#]
    public sealed class Environment
    {
       // Private constructor prevents the class from being created.
       private Environment()
       {
          // Code for the constructor goes here.
       }
    }
    
  • Minimize the amount of work done in the constructor. Constructors should not do more than capture the constructor parameter or parameters. This delays the cost of performing further operations until the user uses a specific feature of the instance.

  • Provide a constructor for every class. If a type is not meant to be created, use a private constructor. If you do not specify a constructor, many programming language (such as C#) implicitly add a default public constructor. If the class is abstract, it adds a protected constructor.

    Be aware that if you add a nondefault constructor to a class in a later version release, the implicit default constructor will be removed which can break client code. Therefore, the best practice is to always explicitly specify the constructor even if it is a public default constructor.

  • Provide a protected (Protected in Visual Basic) constructor that can be used by types in a derived class.

  • You should not provide constructor without parameters for a value type struct. Note that many compilers do not allow a struct to have a constructor without parameters. If you do not supply a constructor, the runtime initializes all the fields of the struct to zero. This makes array and static field creation faster.

  • Use parameters in constructors as shortcuts for setting properties. There should be no difference in semantics between using an empty constructor followed by property set accessors, and using a constructor with multiple arguments. The following three code examples are equivalent:

    ' Example #1.
    Dim SampleClass As New Class()
    SampleClass.A = "a"
    SampleClass.B = "b"
    
    ' Example #2.
    Dim SampleClass As New Class("a")
    SampleClass.B = "b"
    
    ' Example #3.
    Dim SampleClass As New Class("a", "b")
    [C#]
    // Example #1.
    Class SampleClass = new Class();
    SampleClass.A = "a";
    SampleClass.B = "b";
    
    // Example #2.
    Class SampleClass = new Class("a");
    SampleClass.B = "b";
    
    // Example #3.
    Class SampleClass = new Class ("a", "b");
    
  • Use a consistent ordering and naming pattern for constructor parameters. A common pattern for constructor parameters is to provide an increasing number of parameters to allow the developer to specify a desired level of information. The more parameters that you specify, the more detail the developer can specify. In the following code example, there is a consistent order and naming of the parameters for all the SampleClass constructors.

    Public Class SampleClass
       Private Const defaultForA As String = "default value for a"
       Private Const defaultForB As String = "default value for b"
       Private Const defaultForC As String = "default value for c"
    
       Public Sub New()
          MyClass.New(defaultForA, defaultForB, defaultForC)
          Console.WriteLine("New()")
       End Sub
    
       Public Sub New(a As String)
          MyClass.New(a, defaultForB, defaultForC)
       End Sub 
    
       Public Sub New(a As String, b As String)
          MyClass.New(a, b, defaultForC)
       End Sub 
       Public Sub New(a As String, b As String, c As String)
          Me.a = a
          Me.b = b
          Me.c = c
       End Sub
    End Class
    [C#]
    public class SampleClass 
    {
       private const string defaultForA = "default value for a";
       private const string defaultForB = "default value for b";
       private const string defaultForC = "default value for c";
    
       public MyClass():this(defaultForA, defaultForB, defaultForC) {}
       public MyClass (string a) : this(a, defaultForB, defaultForC) {}
       public MyClass (string a, string b) : this(a, b, defaultForC) {}
       public MyClass (string a, string b, string c)
    }
    

See Also

Design Guidelines for Class Library Developers | Class Member Usage Guidelines