#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

Advertisement

#1,022 – How to Use Return Values from All Delegate Instances

If a delegate instance has an invocation list with multiple methods and you invoke the delegate using the standard functional notation, you’ll get back the return value only for the last method in the invocation list.

If you want to consume the return value for each method in a delegate’s invocation list, you can use GetInvocationList to explicitly iterate through the invocation list.

            ReturnIntDelegate del1 = Method1; // Returns 12
            del1 += Method2;  // Returns 99

            // Invoke all at once, get return value
            // only from last
            Console.WriteLine("Invoke normally");
            int val = del1();
            Console.WriteLine(val);

            // Invoke one at a time
            Console.WriteLine("Invoke one at a time");
            foreach (ReturnIntDelegate del in del1.GetInvocationList())
            {
                int ret = del.Invoke();
                Console.WriteLine(ret);
            }

1022-001

#1,021 – What Happens to a Delegate’s Return Value

The return value from a delegate instance is passed back to the caller.  For example:

        private delegate int ReturnIntDelegate();

        static int Method1()
        {
            return 12;
        }

        static void Main(string[] args)
        {
            ReturnIntDelegate del1 = Method1;

            // Invoke
            int val = del1();
            Console.WriteLine(val);
        }

1021-001

Recall, however, that a delegate instance can refer to more than one method.  When a caller invokes a delegate whose invocation list contains more than one method, the value returned to the caller is the return value of the last delegate instance in the invocation list.  Return values of other methods in the invocation list are lost.

        static int Method1()
        {
            return 12;
        }

        static int Method2()
        {
            return 99;
        }

        static void Main(string[] args)
        {
            ReturnIntDelegate del1 = Method1;
            del1 += Method2;

            // Invoke
            int val = del1();
            Console.WriteLine(val);
        }

1021-002

#1,020 – Removing Methods from a Delegate’s Invocation List

You can use the += syntax to add methods to a delegate’s invocation list and then -= syntax to remove methods from its invocation list.  In either case, you add or remove methods that are included in a second delegate’s invocation list from the first delegate’s invocation list.

In the example below, we remove del2’s invocation list (Method2, Method3) from del1’s invocation list (Method1, Method2, Method3, Method4, Method5).  del1’s invocation list then becomes: Method1, Method4, Method5.

            // del1 invokes 5 methods
            StringHandlerDelegate del1 = Method1;
            del1 += Method2;
            del1 += Method3;
            del1 += Method4;
            del1 += Method5;
            del1("del1 Howdy");
            Console.WriteLine();

            // del2 invokes 2 methods
            StringHandlerDelegate del2 = Method2;
            del2 += Method3;
            del2("del2 Howdy");
            Console.WriteLine();

            // Remove del2's methos from del1's invocation list
            del1 -= del2;
            del1("del1 Howdy again");

1020-001
When removing more than one method, the invocation list to be removed must be a contiguous subset of the larger invocation list.  (E.g. {Method2, Method3} rather than {Method2, Method4}).

#1,019 – Syntax for Adding Methods to a Delegate’s Invocation List

If you have a delegate instance, it will have zero or more methods in its invocation list.  When you invoke the delegate instance, these are the methods that will be called.

For a given delegate instance, you can add or remove methods to its invocation list.  In actuality, since a delegate is immutable, you’re actually creating a new delegate instance that has the specified methods added or removed.

Below are several examples of how you might add a new method to the invocation list of an existing delegate instance.

            // Add Method2 to original invocation list
            StringHandlerDelegate del1 = Method1;
            del1 += Method2;
            del1("Howdy 1");

            // Does the same thing
            del1 = Method1;
            del1 = del1 + Method2;
            del1("Howdy 2");

            // Does the same thing
            del1 = Method1;
            del1 = (StringHandlerDelegate)Delegate.Combine(del1, new StringHandlerDelegate(Method2));
            del1("Howdy 3");

1019-001

#1,018 – Delegate Invocation Syntax

In C#, you typically invoke a delegate by using the variable referring to the delegate instance as if it were a method.

For example, in the code below, the variable del1 is a delegate instance and you invoke it by using del1 as if it was a method.

        static void Method1(string text)
        {
            Console.WriteLine(text);
        }

        static void Main(string[] args)
        {
            StringHandlerDelegate del1 = Method1;

            // Invoke the delegate instance
            del1("Invoked through delegate");

            Console.ReadLine();
        }

Alternatively, you can call the Invoke method on the delegate instance.  This does exactly the same thing as the example above.

            // Invocation, method #2
            del1.Invoke("Also invoked thru delegate");

#1,017 – Delegate Types vs. Delegate Instances

In C#, the idea of a delegate is that you create an object that refers to a method.  This object can be thought of as a sort of pointer to the method.

delegate type defines a signature for a method (number and type of parameters and return type).  Below, StringHandlerDelegate is a delegate type.

private delegate void StringHandlerDelegate(string s);

delegate instance is an instance of a delegate type that can refer to one or more methods.  Below, del1 is a delegate instance.

static void Main()
{
    StringHandlerDelegate del1 = Method1;
}

static void Method1(string text)
{
    Console.WriteLine(text);
}

Technically, the term delegate refers to the delegate type, rather than the delegate instance.  But to avoid confusion, you could always refer explicitly to either the delegate instance or the delegate type.

#1,016 – Retrieving the Length of an Array

You can use the Length property of an array to get the number of elements in the array.

For a one- or multi-dimensional arrays, the length is always the total number of elements.  For a jagged array (array of arrays), the length is the number of elements in the outer dimension.

            int[] someNumbers = { 5, 16, 12, 38, 78, 63 };
            // Length = 6
            Console.WriteLine(someNumbers.Length);

            int[,] twoDimensional = { { 3, 2, 1 }, { 1, 2, 3 }, { 4, 6, 8 } };
            // Length = 9
            Console.WriteLine(twoDimensional.Length);

            int[][] jagged = new int[3][] {
                new int[] { 1, 2, 3 },
                new int[] { 4, 8 },
                new int[] { 10, 20, 30, 40 } };
            // Length = 3
            Console.WriteLine(jagged.Length);

1016-001

#1,015 – Rendering a Byte Array as a Series of Hex Characters

You can use the BitConverter class to get a hex representation of a string of bytes.

For example:

            byte[] someBytes = { 0x83, 0xDF, 0x0A, 0xA3, 0x92 };

            string hex = BitConverter.ToString(someBytes);
            Console.WriteLine(hex);

1015-001

#1,014 – Using default Operator in a Generic Class

The default operator provides a valid default value for any type.

One place where this operator is very handy is in a generic class, operating on the type parameter T.  In the example below, we initialize an internal collection of type T so that each element has the proper default value.

    public class BagOf<T>
    {
        private Collection<T> coll;
        public T SomeItem
        {
            get { return coll[0]; }
        }

        public BagOf(int numInBg)
        {
            if (numInBg <= 0)
                throw new Exception("Must have >0 items");

            coll = new Collection<T>();
            for (int i = 0; i < numInBg; i++)
                coll.Add(default(T));
        }
    }

Using this class, we can see the default values for each type of item.

            // Numeric
            BagOf<int> bagOfInt = new BagOf<int>(2);
            int anInt = bagOfInt.SomeItem;

            // Struct
            BagOf<Point3D> bagOfPoints = new BagOf<Point3D>(3);
            Point3D aPoint = bagOfPoints.SomeItem;

            // Reference type
            BagOf<Dog> bagOfDogs = new BagOf<Dog>(4);
            Dog aDog = bagOfDogs.SomeItem;

1014-001