HomeSearch

C# Constructor Examples

Initialize new objects with constructors. Use the new keyword and overloads.
Constructor. The tortoise emerges from its egg. It is hungry so it starts to eat a tasty plant. All things have beginnings. A class is created with a constructor—this is its beginning.
New. In C# a constructor carries the same name as its class. We invoke a constructor with "new." A constructor can have multiple (overloaded) versions.Class
An intro. Here is a public constructor with 1 formal parameter. In Main, we invoke this constructor (with the new keyword) to create new instances of the Widget type.

Widget: A Widget is a term for a "thing." It is often employed by lazy example writers in documentation.

Result: The program creates a Widget with size 10, and then another with size 20.

C# program that uses constructor class Widget { int _size; public Widget(int size) { this._size = size; } } class Program { static void Main() { Widget widget1 = new Widget(10); Widget widget2 = new Widget(20); } }
Base constructor. If we have to add a constructor to a derived class, the base keyword is often useful. This will have the derived constructor invoke the base class constructor.Base

Here: We have a Parrot class that derives from the Bird class (which derives from object).

Parrot: The Parrot constructor has a "base" constructor call (which means the Bird constructor is called when a Parrot is created).

C# program that uses base constructor using System; public class Bird { public Bird(int value) { Console.WriteLine($"Bird() called with {value}"); } } public class Parrot : Bird { public Parrot(int value) : base(value) { Console.WriteLine($"Parrot called with {value}"); } } class Program { static void Main() { Parrot parrot = new Parrot(450); Console.WriteLine(":::DONE:::"); } } Output Bird() called with 450 Parrot called with 450 :::DONE:::
This constructor. Sometimes in a class we have many constructors. We can use "this" to have one constructor invocation call another constructor method. This reduces code bloat.

Tip: Making code easy to read and understand should be a design goal for many classes.

Tip 2: The this-keyword allows code to be shared between the constructors. Constructor initializers are useful in nontrivial classes.

Example: The Mouse class has 2 constructors. The first constructor has no parameters. It calls into the second constructor with "this."

Keyword: The this-keyword here instructs the compiler to insert a call to the specified constructor at the top of the first constructor.

C# program that uses this, constructor using System; class Mouse { public Mouse() : this(-1, "") { // Uses constructor initializer. } public Mouse(int weight, string name) { // Constructor implementation. Console.WriteLine("Constructor weight = {0}, name = {1}", weight, name); } } class Program { static void Main() { // Test the 2 constructors for Mouse type. Mouse mouse1 = new Mouse(); Mouse mouse2 = new Mouse(10, "Sam"); } } Output Constructor weight = -1, name = Constructor weight = 10, name = Sam
Default constructor. Classes have default constructors. These constructors are injected into all class declarations that do not introduce other constructors. This simplifies syntax.

Example: This program shows how the default constructor is added to all classes that have no explicitly defined constructors.

C# program that uses default constructor in class using System; class Test // Has default parameterless constructor { public int Value { get; set; } } class Program { static void Main() { // Call the default constructor. Test test = new Test(); test.Value = 1; Console.WriteLine(test != null); } } Output True
Notes, default constructor. In the .NET Framework, C# code is compiled into an intermediate representation. The default constructors in this program are added there.IL

Here: We see next the intermediate language of the default constructor that was silently added.

Note: This constructor is invoked in the Main method. It calls into the base class constructor, which is the System.Object constructor.

Test constructor: IL .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: call instance void [mscorlib]System.Object::.ctor() L_0006: ret }
Public constructor. Public constructors allow a class to be instantiated from an external location in a program. Most constructors will be in the public accessibility domain.Public, private

Test: This class has a custom constructor that receives a parameter. The constructor uses parameter validation.

ArgumentException

Info: Classes without a public constructor will have an "implicit public constructor" one added automatically by the C# compiler.

C# program that uses public constructor using System; class Test { public Test(int a) { if (a == 0) { throw new ArgumentException("Error", "a"); } } } class Program { static void Main() { Test test = new Test(5); } } Output (The class is instantiated.)
Private constructor. A private constructor cannot be externally called. It can ensure higher-quality code. It forces the class to provide a controlled and unified access pattern.

Example: The private constructor ensures that it is impossible for the class to be instantiated directly from external classes.

Test: This class has a private constructor and 2 fields. The constructor initializes the public int field A to be equal to 5.

Singleton: A private constructor can enforce the singleton design pattern. External code (without reflection) can never create an instance.

SingletonReflection
C# program that uses private constructor using System; public sealed class Test { public static readonly Test Instance = new Test(); // Singleton pattern. public int A; // Instance field. private Test() // This is the private constructor. { this.A = 5; } } class Program { static void Main() { // We can access an instance of this object that was created. // ... The private constructor was used. Test test = Test.Instance; // Use the class instance. Console.WriteLine(test.A); test.A++; Console.WriteLine(test.A); } } Output 5 6
Benchmark, constructors. Let's look at 2 patterns used to initialize member variables in classes. The first pattern sets the fields. The second uses a special overloaded constructor.

Version 1: The constructor C1 is empty. We set the fields in the class in statements in the Main method.

Version 2: The constructor C2 receives 2 arguments, and assigns the class's fields in the body of the constructor.

Results: Version 2 (class C2) is more efficient—when the constructor handles its assignments, the code is both more readable and faster.

C# program that benchmarks constructors using System; using System.Diagnostics; class C1 { public int A; public int B; public C1() { } } class C2 { int A; int B; public C2(int a, int b) { A = a; B = b; } } class Program { const int _max = 1000000; static void Main() { var s1 = Stopwatch.StartNew(); // Version 1: set fields in separate statements. for (int i = 0; i < _max; i++) { C1 c = new C1(); c.A = 1; c.B = 2; } s1.Stop(); var s2 = Stopwatch.StartNew(); // Version 2: set fields in constructor body. for (int i = 0; i < _max; i++) { C2 c = new C2(1, 2); } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } } Output 4.38 ns C1() 2.95 ns C1(1, 2)
Benchmark, discussion. The results show that the overloaded constructor C2 is more efficient. To investigate further, we can look at the MSIL instructions.

Note: You will find that the class C1 code has more instructions related to the evaluation stack.

MSIL code example for C1 L_001c: stloc.3 L_001d: ldloc.3 L_001e: ldloc.2 L_001f: stfld int32 Program/C1::A MSIL code example for C2 L_000d: ldarg.0 L_000e: ldarg.2 L_000f: stfld int32 Program/C2::B
Expression-bodied constructor. A shorter syntax form can be used to specify a constructor. We can use an expression for the constructor's body.

Here: Look at the Dog constructor. It initializes the "paws" field to the value 4. Be careful not to use surrounding parentheses here.

C# program that uses expression-bodied constructor using System; class Dog { int paws; // Expression-bodied constructor. // ... Do not use parentheses around the right side. public Dog() => paws = 4; // Expression-bodied property. public int Paws { get => paws; } } class Program { static void Main() { Dog dog = new Dog(); // Use property to get value of paws. Console.WriteLine(dog.Paws); } } Output 4
Destructor. The C# language is garbage-collected. You do not need to manually free memory. But in certain cases, types need to execute statements when they are no longer used.Destructor

Note: Destructors may be useful in certain situations. Usually they are not. They should be seldom used.

Static. A static constructor is a type initializer. It can execute instructions when a type is first accessed. Conceptually this resembles lazy instantiation.Static Constructor

Info: The time at which the static constructor executes is not guaranteed—but it will occur before code requires it.

Caution: A static constructor can slow down accesses to the members of a class. This is hard to test.

String. Usually you need no constructor when using a string. But a string constructor exists, and it is used to create strings in different ways.String Constructor
Some research. Constructors are a standardized form of init() methods. Language designers felt that using init() is "inelegant." So a special syntax form was introduced.

Quote: The use of functions such as init() to provide initialization for class objects is inelegant and error-prone.... A better approach is to allow the programmer to declare a function with the explicit purpose of initializing objects (The C++ Programming Language).

A review. There are many kinds of constructors in the C# language. We use constructors to make code clearer. With them, we formalize how objects are created.
© 2007-2019 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.
Home
Dot Net Perls