#697 – Encapsulation is Managed through the Use of Access Modifiers

Encapsulation is one of the core principles of object-oriented programming.  Encapsulation is the idea of hiding implementation details of a class from the users of that class and only exposing a public interface.

When you author a class in C#, you can decide which class members (e.g. properties, fields, methods, events, etc) are visible to users of the class.  You do this by using access modifiers to indicate the accessibility of each class member.

Making some class members private allows hiding data from the users of the class, which supports the principle of encapsulation.  Encapsulation is also achieved by preventing access to methods whose use are internal to the code in the class.

#696 – Using a Static Property to Count Instances

A static property is a property that allows access to a data item that is shared across all instances of a class, as opposed to an instance property, where there is a separate copy of the data for each instance.

One common use for a static property is to count the total number of instances of a particular class.  In the example below, the static NumDogs property keeps track of the total number of Dog objects.

    public class Dog
    {
        // Name / Age properties go here

        // Instance constructor
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
            NumDogs++;
            Console.WriteLine(string.Format("Constructor, # dogs now = {0}", NumDogs));
        }

        // Finalizer
        ~Dog()
        {
            NumDogs--;
            Console.WriteLine(string.Format("Finalizer, # dogs now = {0}", NumDogs));
        }

        // Static properties
        public static int NumDogs { get; protected set; }
    }

If we do the following:

            Dog d = new Dog("Kirby", 15);

            Dog d2 = new Dog("Ruby", 2);
            d = d2;

            GC.Collect();

We get:

#695 – Static Methods Can Access Static Members

A static method can only access static members in the class that it’s defined in.

(If you pass an instance of an object to a static method, it can invoke instance members on that object).

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

        // Instance constructor
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }

        // Instance method
        public void Bark()
        {
            Console.WriteLine("{0} says WOOF", Name);
        }

        // Static property
        public static string DogMotto { get; protected set; }

        // Static constructor
        static Dog()
        {
            DogMotto = "Serve humans";
        }

        // Static method
        public static void AboutDogs()
        {
            // Accessing static data
            Console.WriteLine("Dogs believe: {0}", DogMotto);

            // ERROR: Can't access instance property
            Console.WriteLine(Name);

            // ERROR: Can't call instance method
            Bark();
        }
    }

Trying to access instance methods or data from a static member will generate a compile-time error.

#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;
        }

#691 – Use the this Keyword to Trigger Intellisense

Another use of the this keyword, which refers to the current instance of a class, is to trigger Intellisense in Visual Studio so that you can  see a list of members in the class.

For example, let’s say that you’re writing some code for the Bark method in a Dog class.  You want to call another method in the Dog class, but you can’t remember its name.  You can just type this and a period (.).  After typing the period, an Intellisense window will pop up to show you the members in the Dog class.

You can then select the method that you want to call and Intellisense will remind you of what parameters are required.