C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Part 1: Here we invoke the constructor (with the new keyword) to create new instances of the Widget type.
Part 2: The Widget constructor receives the integer size parameter. It assigns the field in the class to the argument.
C# program that uses constructor
class Widget
{
int _size;
public Widget(int size)
{
// Part 2: execute constructor logic.
this._size = size;
}
}
class Program
{
static void Main()
{
// Part 1: invoke constructor.
Widget widget1 = new Widget(10);
Widget widget2 = new Widget(20);
}
}
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:::
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
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
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
}
Test: This class has a custom constructor that receives a parameter. The constructor uses parameter validation.
ArgumentExceptionInfo: 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.)
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.
SingletonReflectionC# 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
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.
Result: 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)
Note: We 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
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
Note: Destructors may be useful in certain situations. Usually they are not. They should be seldom used.
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.
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).