#1,029 – How to Define a Constructor in a Generic Type

When you define a generic type, you include one or more type parameters in the declaration of the type, indicating the type of the type arguments that you specify when constructing an instance of the type.

As with other types, you can define one or more constructors in a generic type.  The constructor uses the name of the type, but without the associated type parameters.  You can, however, have constructors that accept parameters whose type is one of the type parameters.

In the example below, the second constructor makes use of the T type parameter.

    public class PileOf<T>
    {
        private List<T> thePile;

        public PileOf()
        {
            thePile = new List<T>();
        }

        public PileOf(T firstThingInPile)
        {
            thePile = new List<T>();
            thePile.Add(firstThingInPile);
        }

        public void AddThing(T thing)
        {
            thePile.Add(thing);
        }
    }

We can then use this type as follows:

            PileOf<Dog> intPile = new PileOf<Dog>(new Dog("Bowser"));
            intPile.AddThing(new Dog("Fido"));

#1, 023 – Fields Are Initialized Before Execution of Constructors

When you declare a field in a class and initialize the field when it is declared, the initialization of the field will happen when an instance of the class is created, but before the constructor is invoked.  All fields are initialized before the constructor executes, in the order in which they are declared.

Assume that we have a Dog class defined as follows:

    public class Dog
    {
        public string Sound = "Woof";
        public Cat Friend = new Cat("Garfield");
        public string Name { get; set; }

        public Dog(string name)
        {
            Console.WriteLine("Dog constructor for {0}, Sound is {1}", name, Sound);
            Name = name;
        }
    }

When we create an instance of a Dog, the Sound and Friend fields are initialized before the Dog constructor is invoked.

            Dog d = new Dog("Kirby");

1023-001

#874 – An Exception Can Be Thrown from a Constructor

You can throw an exception from a constructor.  For example, in the code below, the Dog constructor throws an exception if an invalid age parameter is passed in.

        // Dog constructor
        public Dog(string name, int age)
        {
            if ((age < 1) || (age > 29))
                throw new ArgumentException("Invalid dog age");

            Name = name;
            Age = age;
        }

The code below catches an exception that happens during construction. Note that the Dog object was never instantiated, so the reference is still null.

            Dog myNewDog = null;

            try
            {
                myNewDog = new Dog("Methuselah", 43);
                Console.WriteLine("We just created an old dog");
            }
            catch (Exception xx)
            {
                Console.WriteLine(
                    string.Format("Caught in Main(): {0}",
                                  xx.Message));
                bool nullDog = (myNewDog == null);
                Console.WriteLine(
                    string.Format("myNewDog is null = {0}", nullDog));
            }

874-001

#824 – A Copy Constructor Makes a Copy of an Existing Object

A copy constructor is a constructor that you can define which initializes an instance of a class based on a different instance of the same class.

In the example below, we define a copy constructor for Dog.  The constructor creates a new instance of a Dog based on an existing instance.

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        // Constructor that takes individual property values
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }

        // Copy constructor
        public Dog(Dog otherDog)
        {
            Name = otherDog.Name;
            Age = otherDog.Age;
        }
    }

Example of using the copy constructor:

            // Create a dog
            Dog myDog = new Dog("Kirby", 15);

            // Create a copy of Kirby
            Dog other = new Dog(myDog);

824-001

#820 – A Protected Constructor Allows a Subclass to Create Instances

You can declare a constructor as private to prevent client code from directly instantiating an object.  But then you can no longer subclass the class, because the derived class won’t have access to the constructor.

If you want private constructor semantics, but still be able to create a subclass, you can make a constructor protected.  Other code won’t be able to construct instances of the base class, but your subclass will be able to call the constructor.

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        protected Dog()
        {
            Console.WriteLine("Constructing Dog");
        }
    }

 

    public class Terrier : Dog
    {
        public double FeistyFactor { get; set; }

        // Implicitly invokes default constructor in base class
        public Terrier(string name, int age, double feistyFactor)
        {
            Console.WriteLine("Constructing Terrier");
            Name = name;
            Age = age;
            FeistyFactor = feistyFactor;
        }
    }

820-001

#819 – A Private Constructor May Prevent Inheritance

You can make a constructor private to restrict creation of an instance of the class only to code within the class.

If all constructors in a class are private, this means that a derived class is also prevented from calling a constructor.  Because the derived class must be able to call some constructor on the parent class, this will effectively prevent the creation of any derived class.

Assume that a Dog class defines a single constructor and makes it private.  In the code shown below, the Terrier class defines a constructor, which would implicitly call the default constructor in the base class.  Because that constructor is private, we get a compiler error and can’t create the Terrier class.

    public class Terrier : Dog
    {
        public double FeistyFactor { get; set; }

        public Terrier(string name, int age, double feistyFactor)
        {
            Name = name;
            Age = age;
            FeistyFactor = feistyFactor;
        }
    }

819-001

#818 – What Happens When an Instance Constructor Throws an Exception

It’s possible for a normal instance constructor to throw an exception.  You can catch any exception thrown from an instance constructor and you’ll get the exact exception that was thrown.  (As opposed to exceptions thrown from static constructors, where you’ll get a TypeInitializationException).

When the exception occurs, the associated instance of the type will not be created.  The class will still function, however–you can create other instances of the type (assuming that the constructor doesn’t throw another exception) and you can access static members of the class.

        public Dog(string name, int age)
        {
            if (name == "Lassie")
                throw new Exception("No Lassies allowed");

            Name = name;
            Age = age;
        }

 

        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine(Dog.DogMotto);
                Dog d = new Dog("Lassie", 12);
            }
            catch (Exception xx)
            {
                Console.WriteLine("Error: {0}", xx.ToString());
            }

            Console.WriteLine(Dog.DogMotto);
            Dog d2 = new Dog("Bowzer", 10);
            d2.Bark();
        }

818-001

#782 – You Can Create an Instance of a struct Without the new Keyword

Like a class, you can create an instance of a struct using the new keyword.  You can either invoke the default parameterless constructor, which initializes all fields in the struct to their default values, or you can invoke a custom constructor.

            // Method 1 - Parameterless constructor, data in struct initialized to default values
            DogCollar collar = new DogCollar();

            // Method 2 - Call custom constructor
            DogCollar collar2 = new DogCollar(10.0, 0.5);

In either case, a constructor is called.

You can also create an instance of a struct by just declaring it, without using the new operator.  The object is created, although you can’t use it until you’ve explicitly initialized all of its data members.

            // Method 3 - Just declare it
            DogCollar collar3;

            // Error - Can't use collar3 yet (use of unassigned field)
            Console.WriteLine(collar3.Length);

We need to first initialize all data members:

            // Correct - initialize first
            DogCollar collar3;
            collar3.Length = 10.0;
            collar3.Width = 5.0;
            Console.WriteLine(collar3.Length);

#768 – When to Call the Constructor of a Base Class

You can use the base keyword in a constructor, to call the constructor of a class’ base class.  You’d most typically do this to allow the constructor in the base class to initialize the data members that are defined in the base class.  Then the constructor of the derived class can initialize its own data members.

In the example below, the Terrier constructor uses the base keyword to invoke the Dog constructor.  Note that the Dog constructor will be executed first.

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public Dog(string name, int age)
        {
            Console.WriteLine("Dog constructor");
            Name = name;
            Age = age;
        }
    }

    public class Terrier : Dog
    {
        public double GrowlFactor { get; set; }

        public Terrier(string name, int age, double growlFactor)
            : base(name, age)
        {
            Console.WriteLine("Terrier constructor");
            GrowlFactor = growlFactor;
        }
    }

768-001

#704 – Using an Object Initializer with Any Constructor

One common pattern for using an object initializer to initalize select properties or fields of an object is to use the following syntax.

            Dog d = new Dog { Name = "Bowzer", Age = 2 };

When using this syntax, the default (parameterless) constructor for the class is called. After the object is constructed, the specified values are assigned to the appropriate properties.

You can also  construct the object using any custom constructor, followed by an object initializer.

For example, let’s say that the Dog class only has a single constructor, which takes two arguments to set the Name and Age properties.  You can then do the following:

            Dog d = new Dog("Bowzer", 2) { CollarSize = 12.4 };

The constructor is called, setting Name and Age. After the object is constructed, the CollarSize property is initialized to contain a value of 12.4.