#616 – Base Class Needs to Know If Polymorphism Is Desired

Let’s say that you design a Dog class that contains a Bark method and that you don’t do anything special to design for inheritance.

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

Now let’s say that you define several classes that inherit from Dog and provide their own implementation for the Bark method.  Because Dog.Bark was not marked as virtual, they must use the new keyword.

    public class Terrier : Dog
    {
        public new void Bark()
        {
            Console.WriteLine("Terrier says Grrrr");
        }
    }

But now you do not get polymorphic behavior when treating instances of Terrier as instances of Dog.

        static void Main()
        {
            Terrier t = new Terrier();
            t.Bark();  // Terrier.Bark
            SomeoneBark(t);
        }

        static void SomeoneBark(Dog d)
        {
            d.Bark();  // Dog.Bark always invoked--no polymorphism
        }

To achieve polymorphism, you must design for it in the base class by marking a method as virtual.

Advertisement

#615 – You Can’t Remove a Base Class Member

A subclass class inherits public members from its base class.  Below, the Terrier class inherits the Name property and the Bark method from the Dog class.

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

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

    public class Terrier : Dog
    {
        public string Temperament { get; set; }
    }
            Terrier jack = new Terrier();
            jack.Bark();   // Woof

The Terrier class can provide a new implementation of the Bark method:

    public class Terrier : Dog
    {
        public string Temperament { get; set; }

        public new void Bark()
        {
            Console.WriteLine("Grrr, growf!");
        }
    }

But you can’t completely remove the Bark method from the Terrier class.  If you try making the Bark method in Terrier private, when you invoke the Bark method on a Terrier object, the method in the parent Dog class will be called instead.

#614 – Subclass Accessibility

A class can be defined with one of two different levels of accessibility:

  • public – all code can use the class
  • internal – only code in the same .exe or .dll can use the class

When you define a subclass, the accessibility of the subclass must be the same as, or less accessible than, the parent class.

This means:

  • If the parent class is public
    • Subclass can be public or internal
  • If the parent class is internal
    • Subclass must be internal

#613 – Interfaces Cannot Contain Static Members

An interface is a list of methods, properties, events and indexers that a class may implement.  All methods, properties and events defined in the interface are implicitly instance members, rather than static members.

    public interface IDogStuff
    {
        bool CanBark { get; set; }
        void Bark();

        // Compile-time Error: The modifier 'static' is not valid for this item
        static string GenerateMotto();

    }

#612 – Members of an Interface Are Implicitly Public

The idea of an interface is to define a contract that a class can choose to implement.  Since an interface is a public definition of a contract, it doesn’t make sense for members of an interface to be private.  This means that all members in an interface are implicitly public.

    public interface IDogStuff
    {
        // Implicitly public
        bool CanBark { get; set; }
        void Bark();

        // Compile-time Error: The modifier 'public' is not valid for this item
        public void Fetch();

        // Compile-time Error: The modifier 'private' is not valid for this item
        private void PeeOnTree();
    }

#611 – Accessibility of Members in a struct

Methods, field and properties within a struct can have one of three access modifiers, dictating the visibility of these members.

  • public – all code has access
  • private – only code within the struct has access
  • internal – code within the defining assembly has access
    public struct DogBark
    {
        public string BarkSound;
        public int BarkLength;

        // Constructor is public
        public DogBark(string barkSound, int barkLength)
        {
            BarkSound = barkSound;
            BarkLength = barkLength;
            hash = barkSound.GetHashCode();
        }

        // internal - accessible from code in the same assembly
        internal int GetHash()
        {
            return hash;
        }

        // private - accessible from code in this struct
        private int hash;
    }

#610 – Lazy Evaluation in Property Get Accessors

One of the benefits in using a property in a class, rather than a public field, is that you can delay calculation of the property’s value until client code actually tries to read the value.

In the code below, we define a FullDogDescription property that is read-only.  The private backing variable is initialized to an empty string and we only calculate its value in the get accessor when someone tries to read the property’s value.

<pre>        private string fullDogDescription = "";
        public string FullDogDescription
        {
            get
            {
                // Generate full description the first time that
                // someone reads this property.
                if (fullDogDescription == "")
                    fullDogDescription = GenerateDogDescription();

                return fullDogDescription;
            }
        }

The benefit of doing this is that if the call to GenerateDogDescription takes some time, we don’t spend the time calculating a value until some piece of code actually needs a value.

#609 – Omit the Class Name for Static Members in the Same Class

Normally when you reference static members, you use the class name where they are defined to prefix the name of the member.  For example, if we have a static property in the Dog class called Motto and a static method called ListAllDogs, we’d use these static members from another class as follows:

    public class Program
    {
        static void Main()
        {
            // Reference static members in Dog from outside of Dog class
            Console.WriteLine("Dog motto: {0}", Dog.Motto);
            Dog.ListAllDogs();
        }
    }

However, if we access these static members from code within the Dog class itself, we can omit the class name when referencing the static members.

        // Dog.Bark
        public void Bark()
        {
            Console.WriteLine("{0} says Woof", Name);

            // Reference static members from within Dog class
            Console.WriteLine("Dog motto: {0}", Motto);
            ListAllDogs();
        }

#608 – Instance Methods Can Use Static Data

Instance methods in a class can make use of any of the public or private static data that belongs to that class.  (They can also make use of static data from other classes, provided that it is accessible).

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

        // Static property
        public static Dog LastGuyThatBarked { get; protected set; }

        // Public static data
        public readonly static string TheDogMotto = "Man's Best Friend";

        // Private static data
        private static int TotalNumDogs = 0;

        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
            TotalNumDogs++;
        }

        public void Bark()
        {
            Console.WriteLine("{0} says Woof", Name);

            // Access static property
            Dog.LastGuyThatBarked = this;

            // Access static data
            Console.WriteLine("There are {0} total dogs", Dog.TotalNumDogs);
            Console.WriteLine("Remember our motto: {0}", Dog.TheDogMotto);
        }
    }

#607 – When Do You Need the volatile Keyword?

The volatile keyword attached to a data field tells the compiler that this field may be read or written to by one or more threads at any time.  Values read from the field are therefore dependent on the timing of the different threads that might be writing to the field.  You can also think of it this way–the value of the field is “volatile”–it could change at any time, so the compiler should not make assumptions about the field’s value being static that would lead to incorrect optimizations.  I.e. Optimizations that lead to a thread reading a stale/incorrect value.

So you need to mark a field as volatile when

  • Different threads read and write the field’s value
  • You don’t protect access to the field using some synchronization technique (e.g. lock statement)