How to Do Constructor Chaining in C#

How to do constructor chaining in C#

You use standard syntax (using this like a method) to pick the overload, inside the class:

class Foo 
{
private int id;
private string name;

public Foo() : this(0, "")
{
}

public Foo(int id, string name)
{
this.id = id;
this.name = name;
}

public Foo(int id) : this(id, "")
{
}

public Foo(string name) : this(0, name)
{
}
}

then:

Foo a = new Foo(), b = new Foo(456,"def"), c = new Foo(123), d = new Foo("abc");

Note also:

  • you can chain to constructors on the base-type using base(...)
  • you can put extra code into each constructor
  • the default (if you don't specify anything) is base()

For "why?":

  • code reduction (always a good thing)
  • necessary to call a non-default base-constructor, for example:

    SomeBaseType(int id) : base(id) {...}

Note that you can also use object initializers in a similar way, though (without needing to write anything):

SomeType x = new SomeType(), y = new SomeType { Key = "abc" },
z = new SomeType { DoB = DateTime.Today };

Beginner to C#: How to do constructor chaining, overriding and using :this / :base?

I'll try to explain it as simple as I can.

Constructor overloading

Nothing new here, it's just like overloading any other method - You simply need the same name but a different signature (meaning different parameters passing into the constructor).

Constructor chaining

This is done by using the keyword this - just like in the code samples in your question.

btw, I usually use it to go from the most elaborate constructor to the simplest one.

sample code:

public class Person
{
public Person()
{
Children = new List<Person>();
}

public Person(string firstName)
: this()
{
this.FirstName = firstName;
}

public Person(string firstName, string lastName)
: this(firstName)
{
this.LastName = lastName;
}

public string FirstName { get; }
public string LastName { get; }
public IEnumerable<Person> Children { get; }
}

Of course, setting default values to properties by using constructor chaining is a valid design and I've used it myself when I needed it, but that's usually not the case.

The keyword base

This keyword always refers to the base (or parent) class.
You will see it a lot when overriding methods and properties as well.

When it comes to constructors - your assumption is correct - it does refer to the base (or parent) class.
So when used in a constructor (like in your Circle example), you can control what overload of the base constructors your derived (or child) class constructor will execute.

So, for instance, if your base class contains three constructors, you can choose which one of them you want to call.

c# will chain constructors of derived class to the default constructor of the base class unless specified otherwise.

Please note that if you inherit from a class that has no default (meaning: parameterless) constructor you must specify the : base(...) in your constructors, even if there is only one constructor to your base class (since that's the only way you can pass the needed parameters to it).

C# constructor chaining - changing the order of execution

You can't call constructors inside other constructors. A constructor can only chain another constructor to be called directly before it.

However, to solve your particular issue, you can make a private constructor that can accept both a types of argument, and have your two original constructors both simply chain this one, passing null for the missing argument.

This has the advantage over calling private initialisation methods that it plays nicely with readonly fields (i.e. it still works if myThing is a readonly field):

public class Foo
{
private static Dictionary<string, Thing> ThingCache =
new Dictionary<string, Thing>();
private Thing myThing;

public Foo(string name)
: this(null, name)
{
}

public Foo(Thing tmpThing)
: this(tmpThing, null)
{
}

private Foo(Thing tmpThing, string name)
{
if (tmpThing == null && name == null)
{
throw new System.ArgumentException(
"Either tmpThing or name must be non-null.");
}

doSomeStuff();
if (tmpThing != null)
{
myThing = tmpThing;
}
else
{
if (ThingCache.ContainsKey(name))
{
myThing = ThingCache[name];
}
else
{
myThing = ExternalStaticFactory.GetThing(name);
ThingCache.Add(name, myThing);
}
}
doSomeOtherStuff();
}
}

You could also use named or optional arguments if you are using C# 4.0:

http://msdn.microsoft.com/en-us/library/dd264739.aspx

Constructor chaining with class as parameter

You need to modify these constructors

    public class ClassToPass
{
public int num = 0;
}

class OtherClass
{
int Numeral = 2;
ClassToPass classtestinside;

public OtherClass()//default ctor
{}

public OtherClass(int valuereceived): this(valuereceived, null)//only int ctor
{}

public OtherClass( ClassToPass _Classtest)//classtopass ctor
: this(0, _Classtest)
{
}
public OtherClass(int valuereceived, ClassToPass _Classtest)//master ctor
: this()
{
Numeral = valuereceived;
if (_Classtest != null)
{
classtestinside = _Classtest;
classtestinside.num = 34;
}
}
}

C# Constructor Chaining Clarification

this() is called before the constructor that chains executes. Then the chaining constructor would be called.

A common kind of example constructor chaining involves providing sensible defaults, like this:

class SomeData
{
private string _string;
private int _int;

public SomeData() : this("Default", 42)
{

}

public SomeData(string str) : this(str, 42)
{

}

public SomeData(string str, int num)
{
_int = num;
_string = str;
}
}

This would allow the user of SomeData to instantiate it with any of the constructors.

Arguably, with optional parameters, this is better solved with:

public SomeData(string str = "Default", int num = 42) { } 

With the chained constructors of SomeData, if I called SomeData(), SomeData(string, num) is called first. After returning, the SomeData parameterless constructor has access to the modifications made by the chained constructor.

How to implement the default constructor (using constructor chaining) that sets the Category to Miscellaneous

If you have a fixed set of categories, you can use an enum to store all values.

public enum ProductCategory
{
Electric,
Household,
Garden,
Miscellaneous
}

You can create a default constructor like this:

public enum ProductCategory
{
Electric,
Household,
Garden,
Miscellaneous
}

public class Product
{

public ProductCategory Category { get; }

public Product(ProductCategory category)
{
this.Category = category;
}

public Product() : this(ProductCategory.Miscellaneous)
{
}

}

static void Main()
{
Product p1 = new Product();
Console.WriteLine(p1.Category); // output: Miscellaneous
Console.ReadKey();
}

If you still want to store your category in a string, you can adapt this example. If you want a fixed list of valid categories, you can check if the category is valid in the constructor.



Related Topics



Leave a reply



Submit