#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);
Advertisements

#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.

#694 – Sequence of Events for Chained Constructors

When you chain constructors together using the this keyword, one constructor calls another while an object is being created.

When one constructor chains to another, the constructor being chained to is executed first, followed by the body of the original constructor.

For example, assume that we have three Dog constructors, as shown below.

        public Dog(string name, int age, string favToy)
        {
            Console.WriteLine("name/age/favToy constructor executing");
        }

        public Dog(string name, int age)
            : this(name, age, "ball")
        {
            Console.WriteLine("name/age constructor executing");
        }

        public Dog(string name)
            : this(name, 1)
        {
            Console.WriteLine("name constructor executing");
        }

If we create a Dog object and pass it only a single argument, of type string, the code in the body of each constructor will be executed in the following order:

  • name/age/favToy constructor
  • name/age constructor
  • name constructor

 

#693 – Named Arguments in Constructors Allow the Most Flexibility

If you declare multiple constructors for a class, you can create constructors that support any combination of parameters.

For example:

        public Dog(string name, int age, string favToy)
        {
            // init stuff
        }

        public Dog(string name) : this(name, 1, null) { }
        public Dog(string name, string favToy) : this(name, 1, favToy) { }

Using optional parameters, you can declare a single constructor:

        public Dog(string name, int age = 1, string favToy = null)
        {
            // init stuff
        }

But when you do pass in arguments for any optional parameters, you must pass them in the correct order, without skipping any.

To get around this problem, you can use named arguments when invoking the constructor.

            // Ok to omit age, but then favToy must be named argument
            Dog spot = new Dog("Spot", favToy: "Ball");

#692 – Two Approaches for Optional Parameters in Constructors

When you create an instance of an object, you may want to pass different combinations of parameters for purposes of initializing the object.  In authoring a class, there are a couple different ways to support this.

You can declare multiple constructors, each supporting a different set of parameters.  You can use constructor chaining to invoke the main constructor, to centralize object initialization.

        public Dog(string name, int age, string favToy )
        {
            // Do all parameter validation here
            Name = name;
            Age = age;
            FavoriteToy = favToy;
        }

        public Dog(string name) : this(name, 1, null)
        {
        }

        public Dog(string name, int age) : this(name, age, null)
        {
        }

        public Dog(string name, string favToy) : this(name, 1, favToy)
        {
        }

You can also use optional parameters in a single constructor, to do the same thing.

        public Dog(string name, int age = 1, string favToy = null)
        {
            // Do all parameter validation here
            Name = name;
            Age = age;
            FavoriteToy = favToy;
        }

#670 – Static vs. Instance Initialization

Static fields and properties are data members associated with a class itself, rather with instances of that class.  A static constructor can be used to initialize static members.  Static fields can also be initialized when they are declared.

The first time that you reference a static member, the following occurs:

  • All static fields are initialized
  • The static constructor is called
  • Your code, which accesses the static member, executes

If you reference an instance method, or create an instance of the class, before referencing any static members, the following occurs:

  • All static fields are initialized
  • The static constructor is called
  • All instance fields are initialized
  • The instance constructor is called
  • Your code, which accesses an instance member, executes

For example, initializing an instance of a Dog leads to the output shown below.

Dog d = new Dog();