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

#703 – Object Initializers Allow Setting Either Fields or Properties

When you use an object initializer, you can specify the value that one or more of the object’s properties should take on, after the object is constructed.

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

If your class includes public fields, you can also initialize the fields within the object initializer.

For example:

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

        // Field
        public double CollarSize;

        // Constructors
        public Dog()
        {
        }
    }
            Dog d2 = new Dog { Name = "Kirby", Age = 15, CollarSize = 12.2 };

#702 – An Automatic Property Must Define Both get and set Accessors

When you define an automatic property, you must include both get and set accessors.

        public string Name { get; set; }

It wouldn’t make sense to omit either accessor, since they are the only mechanism for reading from or writing to the property.

Although you can’t strictly create a read-only or write-only automatic property, you can use access modifiers so that the property is effectively read-only or write-only, from outside the class.

        // Automatic property that is read-only from outside class
        public string Temperament { get; protected set; }

        // Automatic property that is write-only from outside class
        public string Password { protected get; set; }

#701 – Centralize Business Rules Logic in set Accessors

You can use a property’s set accessor to enforce business rules for that property, e.g. min/max values for the property.

If you have a constructor that accepts initial values for some properties of a class, or methods that accept values, you can avoid checking constraints on these parameters by delegating the enforcement of the rules to the set accessor.

For example:

    public class Dog
    {
        // Public properties
        public string Name { get; set; }

        private int age;
        public int Age
        {
            get { return age; }

            // Set accessor checks for valid Age values
            set
            {
                if (value != age)
                {
                    if ((value > 0) && (value < 30))
                        age = value;
                    else
                        throw new Exception("Age is out of range");
                }
            }
        }

        // Constructor
        public Dog(string name, int age)
        {
            Name = name;

            // Don't validate age value here, but let set accessor do it
            Age = age;
        }
    }

#700 – Using a set Accessor To Enforce Casing

A set accessor allows client code to give a property a new value.  You typically use the set accessor to do any required validation or conversion of the input value.  This is the point where you impose any business rules related to the value of the property being set.

For example, you might enforce a requirement that a particular string-based property always be uppercase.  Instead of throwing an exception if some calling code tries to set a property that is not uppercase, you can just automatically convert all values to uppercase.

    public class Car
    {
        private string licPlate;
        public string LicPlate
        {
            get { return licPlate; }
            set
            {
                if (value != licPlate)
                {
                    if (value.Length != 7)
                        throw new Exception("Invalid license plate number");
                    else
                        licPlate = value.ToUpper();
                }
            }
        }

    }

 

            Car c = new Car();
            c.LicPlate = "vpn 123";

            Console.WriteLine(c.LicPlate);

#699 – Types Are Implicitly Internal

When you define a type in C#, you can define its accessibility as either public or internal.  Public types are visible to all code.  Internal types are visible only to code within the same assembly.

By default, if you don’t include an access modifier when defining a type, the type’s accessibility will be internal.

In the example below, the Dog class will be visible only to code within the same assembly.

    // No access modifier => type is internal, visible
    //   only to code within the same assembly.
    class Dog
    {
        // Public properties
        public string Name { get; set; }
        public int Age { get; set; }

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

        public void Bark()
        {
            Console.WriteLine("Woof");
        }
    }

#698 – Type Members Are Implicitly Private

You use access modifiers to define the accessibility of members within a class (publicprivate, protected, internal or protected internal).

If you omit the access modifier entirely, the class member defaults to being private.  This is true for all class members, including constants, fields, properties, methods, indexers, events, constructors and nested types.

In the example below, the Description property, NumDogs static property and the ChaseTail method are all effectively private members, because their declaration does not include an access modifier.

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

        // Implicitly private
        string Description { get; set; }

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

        // Implicitly private
        static int NumDogs { get; set; }

        // Implicitly private
        void ChaseTail()
        {
            Console.WriteLine("I'm chasing my tail");
        }
    }

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