This is the first in what I hope will be a long series of quick posts covering the basics of programming in C#. For this first installment, I’ll review the proper use and improper use of a class or struct constructor.
What is a Constructor
In a C# class, a constructor is a special code block for a class or struct called when an instance of that class or struct is created. If a constructor is not defined in code, the compiler will create a default constructor without parameters. Constructors can be overridden and can call a base class constructor.
Proper Use of a Constructor
Use a constructor to set or initialize class or struct fields. If this initialization code is lengthy, such as in the construction of a Windows Form class, move the initialization code to a partial class file and call it something like InitializeComponents. Here are a few examples:
public partial class Apple : Fruit
{
//same as a default constructor if not constructor defined
public Apple()
{
}
//initialize a local class member
public Apple(string name)
{
_name = name;
}
//initialize and call base class constructor
public Apple(string name, double weight) : base(weight)
{
_name = name;
}
//constructor with conditional param to control construction behavior
public Apple(bool initializeAll)
{
if (initializeAll) InitializeComponents();
}
//shown here but often hidden away in another file of defining the partial class
void InitializeComponents()
{
//do some lengthy but simple initialization of class members
}
private string _name;
}
Improper Use of a Constructor
Do not use a constructor for error prone or complex code. Do not use a constructor to execute tasks, business logic. I’m not going to include code examples of bad constructors but here are a few anti-patterns I’ve seen in my travels:
- The constructor makes a call to an external service or database – BAD
- The constructor creates child objects and calls methods on those objects to perform some business function – BAD BAD
- The constructor asks for user input or reads from a file – BAD BAD BAD
Alternatives to a Constructor
If you require lengthy, long running or potentially error prone code to produce an instance object of a class or struct, use either a factory class or a static create method. Here’s how:
public class BookService : IBookService
{
//a private default construtor prevents use of it outside of the class itself
private BookService()
{
}
public static BookService Create()
{
BookService instance = new BookService(); //calls private constructor
//put lenghty or error prone code here that sets up the service
return instance;
}
}
//use a factory for even more complex object creation
public static class BookServiceFactory
{
public static IBookService Create(BookOptions options)
{
IBookService instance;
//based on the BookOptions provide create the proper
//concrete instance of an IBookService interface
return instance;
}
}
Of course this is not a comprehensive treatment. It’s a blog post. If you want more, buy a book. If you have topics you would like to see addressed in future installments, please let me know.