We’ve already covered so many C# concepts, and most of them relate to objects. This is hardly surprising, C# being an object-oriented language. What is surprising is that, up until this point, we haven’t covered the “thing” responsible for creating objects!
Today’s post will remedy this problem by covering the C# constructor. The post will roughly follow the same pattern we’ve followed through much of the series. We start by defining the concept, then proceed to show several usage examples. We part ways with general tips on best practices to follow and pitfalls to be aware of. Let’s begin!
Defining the C# Constructor
To define “C# constructor,” let’s first see what Wikipedia has to say about constructors in general:
In class-based object-oriented programming, a constructor (abbreviation: ctor) is a special type of subroutine called to create an object. It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.
That’s a great definition. In short, the constructor is responsible for creating new objects and getting them ready for use. When you create a new instance from a class or struct, their constructor is automatically called. Constructors are routines that look like methods?though technically they’re not? and have the same name as the class or struct.
The Simplest C# Constructor Example You Could Wish for
Consider the following example:
using System; public class Person { public bool Employed { get; private set;} public Person() { Employed = true; } } class ConstructorExample { public static void Main (string[] args) { Person p = new Person(); Console.WriteLine(p.Employed); } }
In the example above, we define a class called Person with a simple constructor. Then, we instantiate the class using the new operator. As soon as the memory is allocated for the new object, the constructor is called.
C# Constructor in All Shapes and Sizes
Constructors might come in different types. In this section, we will describe some of the main kinds of constructors you might use when writing C# code.
Instance Constructors
This is how the C# specification defines the C# instance constructor:
An instance constructor is a member that implements the actions required to initialize an instance of a class.
You use instance constructors to initialize instance member variables when you create an object from a class by using the new expression. The constructors of the Person class, featured in our previous examples, was an example of instance constructor.
The following example shows another instance constructor:
public class RgbColor { public byte Red { get; private set; } public byte Green { get; private set; } public byte Blue { get; private set; } public RgbColor() { Red = 0; Green = 0; Blue = 0; } }
The constructor in the example above would be called whenever a new instance of RgbColor is created. A constructor like the one above?or like the first constructor in our Person class?is said to be a parameterless constructor.
Parameterless Constructor
In the example above, the RgbColor featured a constructor with no parameters. The same as true for the Person class from our first example. Such constructors are unsurprisingly called parameterless constructors. The parameterless constructor is always called when you create an object by using the new operator and don’t provide any arguments to it.
The thing about parameterless constructors is that all classes have one?unless you explicitly prevent them from having one. Confused? Things will become clearer with an example:
using System; public class Person { public string Name { get;set; } public int Age { get; set; } public override string ToString() => $"My name is {Name} and I'm {Age} years old."; } class ConstructorExample { public static void Main (string[] args) { Person p = new Person(); p.Name = "Miranda Solis"; p.Age = 21; Console.WriteLine(p); } }
We’re still using the Person class from the first example, but we’ve changed it a bit. Now the class has both a Name and Age properties. It also now overrides the ToString() method. More importantly?the class now lacks a constructor. What’s the implication of that? None at all. If you run the code above, you’ll see that it works perfectly. That’s because when a class doesn’t have any constructor, the C# compiler gives it a public, parameterless one. That way, it becomes possible to create instances of the class.
As soon as the class gets a regular constructor that takes parameters, it loses the “automatic” parameterless one. To see that happening, edit the Person class, adding the following code to it:
public Person (string name, int age) { Name = name; Age = age; }
Now the code will fail to compile, and you’ll get the message:
The type `Person’ does not contain a constructor that takes `0′ arguments
To make the error go away, you have two options. You can remove the newly-added constructor?as well as any reference to it?or add an explicit parameterless constructor, like the one the class had back in the first example.
Private Constructors
A private constructor is a special type of instance constructor. It’s used to prevent instances of a given class to be created. How? When a given class has one or more private constructors and no public constructors, it can’t be instantiated by other classes (except nested classes). For instance, it’s common to declare an empty, private constructor in order to prevent classes that only have static members from being instantiated. Keep in mind that in such cases, though, the best alternative would be to make the whole class static.
There is another important usage for private constructors, though. Consider the following example:
public class Distance { private readonly double meters; private Distance(double meters) { this.meters = meters; } public static Distance FromMeters(double meters) { return new Distance(meters); } public static Distance FromKilometers(double kilometers) { return new Distance(kilometers * 1000); } // more methods, properties, etc }
In the example above, the empty private constructor has a very specific purpose?it enforces the usage of the static methods FromMeters and FromKilometers to create instances of the class.
Struct Constructors
Struct constructors look like class constructors, but they have a crucial difference. You’re not allowed to add a parameterless constructor to a struct. That’s because the compiler always provides an automatic one for each struct. This automatic constructor initializes all of the fields in the struct to their default values. To understand, consider the following example:
public struct RgbColor { public byte Red; // this is a bad practice. Don't use writable public fields on structs in real life! public byte Green; public byte Blue; public RgbColor(byte red, byte green, byte blue) { Red = red; Green = green; Blue = blue; } } class ConstructorExample { public static void Main (string[] args) { var color = new RgbColor(); System.Console.WriteLine(color.Red); // this will print 0 } }
In the example above, we create a new instance of the RgbColor struct by using the automatic parameterless constructor. That causes the instance variables to initialize to their default values.
C# Constructor: Best Practices and Pitfalls
To end our post, let’s talk briefly about some general best practices you should follow when working with constructors, and also some pitfalls you need to be aware of.
First of all, try to keep your constructors simple. An ideal constructor should have a small number of parameters. Also, avoid doing any work in the constructor, besides initializing the members of the instance. In special, avoid costly processings, delaying them until they are required.
Consider throwing from the constructor, when appropriate (e.g., for instance, throw ArgumentNullException if you get null for an argument, and null isn’t a valid value.
Be aware when adding a new, parameterized constructor to a class that didn’t have one. Doing so prevents the C# compiler from adding the automatic parameterless constructor, which can cause breaking changes in some situations.
Conversely, use a private constructor when you want to prevent other classes from instantiating your classes with the goal of, for instance, enforcing the usage of a static factory method.
Back to You
Time to part ways. Before we do that, though, keep in mind that what this post covered is just the tip of the iceberg. There’s a lot more to the C# constructor than what could’ve been covered by a single blog post.
If you want to learn more about C#, keep an eye out for more posts on the SubMain blog. We’re always adding new content related to the language. Keep learning and never stop sharpening your saw. Thanks for reading!
Learn more how CodeIt.Right can help you automate code reviews and improve the quality of your code.