#1,205 – C# 6.0 – Using the Null-Conditional when Invoking a Delegate

When you fire an event (by invoking a delegate), you typically need to check for null before invocation.  This avoids a null reference exception if there are no subscribers to the event.

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

        public event EventHandler<string> NameChange;

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                if (value != name)
                {
                    name = value;

                    // Check for null before invocation
                    if (NameChange != null)
                    {
                        NameChange(this, name);
                    }
                }
            }
        }

        public int Age { get; set; }
    }

(The above pattern is not thread-safe).

An alternative pattern is to declare the event with a null handler, so that there is always at least one handler on the invocation list. (This is thread-safe).

In C# 6.0, we can use the null-conditional to invoke a delegate.

                    NameChange?.Invoke(this, name);
Advertisements

#1,159 – Events vs. Delegates, part II

You can use a delegate in place of an event by simply removing the event keyword.  Using an event is preferred, however, because the event syntax prevents different consumers of the event from impacting each other.

Specifically, using a public field that is a delegate allows client code to do any of the following.  These actions are all prohibited when using an event.

  • Prevent other subscribers from being invoked by directly changing the delegate’s invocation list.
  • Delete invocation list by reassigning the delegate instance to null
  • Invoke the delegate directly

These are all actions that should only be allowed by the producer of the event and not by any of its consumers.  The event syntax prevents consumers from interfering with each other.

#1,150 – Generic Delegate Type as Parameter

You can use a generic delegate type as a parameter to a method.

Suppose that we have the following type:

        public delegate T Merger<T>(T thing1, T thing2);

We can now create a method that takes a constructed version of this type as a parameter.  We could then call the method as shown in the Main method.

        static void MergeInts(Merger<int> intMerger, int n1, int n2)
        {
            int result = intMerger(n1, n2);
        }

        public static int Add(int n1, int n2)
        {
            return n1 + n2;
        }

        static void Main(string[] args)
        {
            MergeInts(Add, 5, 6);
        }

We could also define a generic method that has a generic delegate parameter.

        static void MergeSomething<T>(Merger<T> someMerger, T thing1, T thing2)
        {
            T result = someMerger(thing1, thing2);
        }

We can then call this method as follows:

        public static Dog Breed(Dog mama, Dog papa)
        {
                return new Dog(mama.Name + papa.Name);
        }

        static void Main(string[] args)
        {
            MergeSomething(Add, 5, 6);

            Dog dog1 = new Dog("Lassie");
            Dog dog2 = new Dog("Spuds");
            MergeSomething(Breed, dog1, dog2);
        }

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

#637 – A Delegate Can Refer to A Partial Method

You can have a delegate refer to a partial method, but only if the partial method is implemented.  At compile-time, if a delegate points to a partial method and you’re compiling only the declaration of the partial method, but not an implementation, you’ll get a compiler error.

    // Dog-1.cs
    public partial class Dog
    {
        // Action is a delegate type in System that takes
        //   no parameters and returns a void
        Action barkDelegate;

        public Dog()
        {
            // Point delegate to partial method Bark.
            barkDelegate = Bark;
        }

        public void BarkViaDelegate()
        {
            barkDelegate();
        }

        // Partial method declaration--no implementation here
        partial void Bark();
    }
    // Dog-2.cs
    public partial class Dog
    {
        // Implementation of Bark
        partial void Bark()
        {
            Console.WriteLine("Woof!");
        }
    }
        static void Main()
        {
            Dog d = new Dog();
            d.BarkViaDelegate();
        }

#626 – Nested Type Options

When you declare one type inside of another, the outer type must be either a class or a struct.  The inner (nested) type can be one of the following: class, struct, interface, delegate or enum.

Here are a few common examples.

A struct in a class:

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

        public struct DogCollar
        {
            public int Length;
            public string Material;
        }
    }

A delegate type  defined in a class:

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

        public delegate void BarkHandler(object sender, BarkEventArgs e);
    }

An enum in a class:

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

        public enum Temperament { Docile, Excitable, Vicious };
    }

#551 – Use Anonymous Method When Adding to an Invocation List

Recall that an instance of a delegate can refer to more than one method (delegates are multicast).  In addition to using an anonymous method to declare a new instance of a delegate, you can also use anonymous methods when adding a new method to an existing delegate instance.  (Adding to the delegate instance’s invocation list).

        private delegate void StringHandlerDelegate(string s);

        static void Main()
        {
            // Declare new delegate instance, with anonymous
            // method in its invocation list
            StringHandlerDelegate del1 =
                delegate (string s) { Console.WriteLine(s); };

            // Now add a 2nd method to delegate, also using
            // anonymous method
            del1 +=
                delegate(string s) { Console.WriteLine(new string(s.Reverse().ToArray())); };

            // When we invoke the delegate, both methods are
            // called
            del1("Mairzy Doats and Dozy Doats");
        }