Home > Articles > Programming > Windows Programming

.NET Patterns, Part I

Like this article? We recommend

Using Constructors

One of the other concepts that may be new to many developers is the use of constructors that can be parameterized and overloaded to allow parameters to be passed into the instance of a class during its initialization. You should be aware of several guidelines, however, when defining constructors on your classes.

First, make sure that you limit the amount of work done in the constructor. Typically, constructors should only capture the parameters passed to them and initialize private data within the instance. By performing lots of other work, you'll cause the class to appear sluggish and perhaps do extra work for nothing because the user of the class may never call another method on it. Instead, you should defer the work until the user of the class calls the specific feature. Additionally, the parameters that you pass into a constructor should be viewed as shortcuts for setting properties on the class after the class has been created using an empty constructor. Thus, the following two C# code snippets should be semantically equivalent:

QuilogyDataAccess da = new QuilogyDataAccess();
da.Switch = mySwitch;
da.ConnectString = 
"server=ssosa;database=Quilogy;trusted_connection=yes";


QuilogyDataAccess da = new QuilogyDataAccess(
 "server=ssosa;database=Quilogy;trusted_connection=yes", mySwitch);

Note as well that the order in which the properties are set in the first snippet and the order in which they are exposed in the constructor in the second snippet should not matter. In other words, all properties in a class should be able to be set in any order.

Second, in cases when the constructor is overloaded to include different signatures, you should use a consistent ordering and naming pattern for the parameters. The typical approach is to provide an increasing number of parameters, to allow the user of the class to provide more detailed information, if required. In the previous example, the QuilogyDataAccess class might provide the following two constructors:

Public Class QuilogyDataAccess : Inherits IQuilogyDataAccess
 Public Sub New()
  ' implementation
 End Sub

 Public Sub New(ByVal connect As String)
  ' implementation
 End Sub

 Public Sub New(ByVal connect As String, ByVal trace As Switch)
  ' implementation
 End Sub
End Class

In this case, the user can pass in more detailed information by using the second constructor and passing in a class derived from System.Diagnostics.Switch to capture trace output. Along these same lines, C# includes an interesting syntax that allows you to easily allow one constructor to call another using what is referred to as an initializer list. This is useful because it allows a default constructor, for example, to call one of the more specific constructors using default parameters. If the previous class were rewritten in C#, the default (empty) constructor could call one of the other constructors automatically, as follows:

public Class QuilogyDataAccess : IQuilogyDataAccess
{
 public QuilogyDataAccess() : this("server=ssosa")
 {
  // implementation
 } 

 public QuilogyDataAccess(String connect)
 {
  // implementation
 }

 public QuilogyDataAccess(String connect, Switch trace)
 {
  // implementation
 }
}

You can also create constructors that are not public for special purposes. Creating a protected constructor allows derived classes to pass specific information to the base class that it needs to operate while creating an empty private constructor in a class if you don't want instances of the class to be created. The latter technique is useful if the class exposes only shared (static in C#) methods and thus should not be able to be instantiated. Keep in mind that if you do not create a constructor for a class, both C# and VB .NET will create a default constructor that accepts no arguments. However, once you create a constructor that accepts arguments, the compiler does not create the empty constructor.

Finally, constructors must also be considered when you create derived classes. For example, it is often necessary to pass information obtained in a parameterized constructor into the base class. This is the case, for example, when a class derived from Exception accepts a message in its constructor, as the QuilogyException class mentioned previously might do. At first glance, this might seem difficult because you would think that a base class would be must be initialized before its descendant classes. However, both VB .NET and C# include specific syntax that allow you to pass information from a derived constructor to its base class. In VB .NET, this is done by calling the New method of the MyBase object in the first line of the constructor, passing it the arguments that it needs, as shown here:

Public Sub New(ByVal message As String)
 MyBase.New(message)
End Sub

If QuilogyDataAccess were written in C#, the constructor declaration would use the base keyword, like this:

public QuilogyException(String message) : base(message)
{
 // other initialization here
}

In both cases, the base class will be initialized using the message parameter passed to the constructor.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.