Tag Archives: Delegates

Converter Delegate

Another delegate which I think is worth writing a post about is the Converter delegate. This delegate takes the following signature:

Converter<TInput, TOutput>

The idea being, conversion of one type to another. A quick and easy example of this might be if you want to convert a System.String object to a “Registry Hive” object (a root RegistryKey object). The following code demonstrates that:

public static RegistryKey GetRegistryKeyFromString(string name)
{
    return typeof(Registry).GetMembers().OfType<FieldInfo>()
        .Where(f => f.Name.Equals(name, StringComparison.Ordinal))
        .Select(f => f.GetValue(name) as RegistryKey).FirstOrDefault();
}

And usage:

private static Converter<string, RegistryKey> stringToHiveConverter;

static void Main(string[] args)
{
    stringToHiveConverter = Converters.GetRegistryKeyFromString;

    var registryHive = stringToHiveConverter("CurrentUser");
}

While I am talking about the registry, I will take this opportunity to set out a class which I use to abstract away the Registry and operations on it. At the moment, it is not very sophisticated and only really deals with strings. However, if I ever need to evolve it beyond that, this class is a good starting point. And apropos of converters, it contains a converter which converts strings to RegistryView objects. The constructor permits the user of the class to pass it a custom converter, giving the user more control over how that conversion takes place:

Hopefully that class serves you as well as it served me!

Comparison Delegate – Used to Compare (duh)

The comparison delagate has only one signature:

public delegate int Comparison<in T>(T x,T y)

It is a simple little delegate which follows the same rule as CompareTo (IComparable) and Compare (IComparer):

Logic Result
x < y -1
x == y 0
x > y 1

An example of a method in the framework which takes the Comparison delegate as a parameter is the Sort method of the List class. You can create more than 1 method which conforms to this delegate, thereby giving the caller the power to decide how they want the Sort order to be determined:

        private static int CompareEmployees(Employee firstEmployee, Employee secondEmployee)
        {
            if (firstEmployee == null && secondEmployee == null)
            {
                return 0;
            }

            if (firstEmployee == null)
                return -1;
            if (secondEmployee == null)
                return 1;

            return firstEmployee.Nr.CompareTo(secondEmployee.Nr);
        }

        private static int CompareEmployeesReverse(Employee firstEmployee, Employee secondEmployee)
        {
            if (firstEmployee == null && secondEmployee == null)
            {
                return 0;
            }

            if (firstEmployee == null)
                return 1;
            if (secondEmployee == null)
                return -1;

            if (firstEmployee.Nr.CompareTo(secondEmployee.Nr) < 0)
            {
                return 1;
            }
            else if (firstEmployee.Nr.CompareTo(secondEmployee.Nr) > 0)
            {
                return -1;
            }
            else 
                return 0;
        }

And to use it:

            List<Employee> employees = GetEmployees();

            employees.Sort(CompareEmployees);

There’s not too much more to say. This delegate gets used quite a bit in LINQ.

Get the code:

Func Delegate and Default Values

Another really common and useful delegate is the Func delegate. This delegate has many overloads which all return a result. They differ in the number of parameters which they can be passed:
Func Signatures
One scenario in which I have used this delegate is in a SessionState service which I wrote recently, effectively making SessionState strongly typed. By way of example, I have simplified that idea into a Console application which uses a Dictionary collection instead of HttpContext.Current.Session. First, I created the MemoryBucket class:

    internal class MemoryBucket
    {
        private Dictionary<string, object> items;

        internal MemoryBucket()
        {
            items = new Dictionary<string, object>(StringComparer.Ordinal);   
        }

        internal void SetValue<T>(string key, T value)
        {
            if (!this.items.ContainsKey(key))
            {
                items.Add(key, value);
            }
            else
            {
                items[key] = value;
            }
        }

        internal T GetValue<T>(string key, Func<T> createDefault)
        {
            T retval;

            if (!ReferenceEquals(null, items))
            {
                if (items.ContainsKey(key) && items[key].GetType() == typeof(T))
                {
                    retval = (T)items[key];
                }
                else
                {
                    retval = createDefault.Invoke();
                    items[key] = retval;
                }

                return retval;
            }
            else
            {
                throw new NullReferenceException("There is no Memory object available.");
            }
        }
   }

Looking at the GetValue method, if the value passed into this method is either null, or not the same type as the item which correlates to that key, a default value is returned. That default value is determined by the method (or lambda) which the calling code passes in as the 2nd parameter. So, the delegate gives the power to the calling code to control how the default value is generated. For example:

        static void Main(string[] args)
        {
            MemoryBucket bucket = new MemoryBucket();

            bucket.SetValue("My Name", "dave");
            Console.WriteLine(bucket.GetValue("My Name", () => "David"));

            bucket.SetValue("My Name", 10);
            Console.WriteLine(bucket.GetValue("My Name", () => "David"));

            Console.Write("\nPress any key to kill console...");
            Console.ReadKey();
        }

As you can see, the second time I call GetValue follows a call to SetValue which sets the “My Name” item to 10. As the System.Int32 type is not of the same type as the System.String type, the default value will be returned. That value being the string “David”, which is the return value in the lambda expression.

A Different Approach to Flow Control and the Action Delegate

This originally started as a post about the Action delegate. But Recently on StackOverflow, I stumbled across an interesting technique for flow control which differs from the standard if/switch statements approach. The example I will show below uses the Action Delegate.

The Action delegate has a void return type and like many of the System delegates, it has a large number of overrides which cater for differing numbers of parameters:

In this example, I am using 2 different overrides of the Action delegate in conjunction with a couple of dictionaries. First up, I create the dictionaries:

    public partial class MainWindow : Window
    {
        private IDictionary<string, Action> clearControlsDelegateBucket;
        private IDictionary<string, Action<CanExecuteRoutedEventArgs>> buttonCanExecuteDelegateBucket;
        public MainWindow()
        {
            clearControlsDelegateBucket = new Dictionary<string, Action>(2, StringComparer.Ordinal)
                                              {
                                                  {"ClearTextBoxButton", ClearTextBox},
                                                  {"ClearAllControlsButton", ClearAllControls}
                                              };
            buttonCanExecuteDelegateBucket = new Dictionary<string, Action<CanExecuteRoutedEventArgs>>(2, StringComparer.Ordinal)
                                         {
                                             {"ClearTextBoxButton", TextBoxCanClear},
                                             {"ClearAllControlsButton", ControlsCanClear}
                                         };
            InitializeComponent();

The UI looks like this:

<Window x:Class="ActionDelegate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ActionDelegate.CustomCommands" Title="MainWindow" Height="145" Width="225">
        
    <Window.CommandBindings>
        <CommandBinding Command="local:ClearUiControlCommand.ClearControls" CanExecute="CanClear" Executed="ClearControls_Executed"></CommandBinding>
    </Window.CommandBindings>        
        
    <Grid>
        <StackPanel>
            <CheckBox x:Name="CheckedCheckBox" Content="This is initially checked" IsChecked="True" Margin="10,2,10,2" />
            <TextBox x:Name="TextBoxWithText" Text="This text is here" Margin="10,0,10,2" />
            <Label x:Name="LabelWithText" Content="This label content is here" Margin="10,0,10,2" />
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Button x:Name="ClearTextBoxButton" Width="100" Content="Clear TextBox" Command="local:ClearUiControlCommand.ClearControls" />
                <Button x:Name="ClearAllControlsButton" Width="100"  Content="Clear All Controls" Command="local:ClearUiControlCommand.ClearControls"  />
            </StackPanel>
        </StackPanel>        
    </Grid>
</Window>

As you can see, I have bound the 2 clear buttons, ClearTextBoxButton and ClearAllControlsButton, to the same command ClearUiControlCommand.ClearControls. The Executed property of that custom command is set to the handler ClearControls_Executed. So, if the button can execute, it runs the following code:

        private void ClearControls_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Button clickedButton = e.OriginalSource as Button;
            String buttonName = clickedButton.Name;

            clearControlsDelegateBucket[buttonName].Invoke();
        }

You can see there how it has accessed the relevant dictionary item by way of the key which we gave to it in the constructor. That key being the same as the name of the button which was clicked. I then invoke the Action delegate stored at that item in the collection.

So, there is an interesting alternative to conventional flow control, using the Action delegate and an IDictionary collection.

Get the code:

Delegates Explained – Part 4

The Delegates Series:

  1. Delegates Explained – Part 1
  2. Delegates Explained – Part 2
  3. Delegates Explained – Part 3
  4. Delegates Explained – Part 4 <<

In this last post in this series, I want to examine what the event keyword buys us in the subscriber model for handling events.

Consider our previous example. Recall that the notification delegate of the DvdStore class is public. Now, what would happen if we set the Notification delegate to a totally new delegate object? It would blow away the list of delegates which had previously been subscribed, is the short answer. Try it yourself and see.

        static void Main(string[] args)
        {
            DvdStore theStore = new DvdStore();

            theStore.notification += new NotifyDvdArrived(BroadcastArrivalOfDvdByBatSignal);
            theStore.notification += new NotifyDvdArrived(BroadcastArrivalOfDvdByLoudSpeaker);
            theStore.notification += new NotifyDvdArrived(BroadcastArrivalOfDvdBySnailMail);

            theStore.notification = delegate
                                        {
                                            Console.WriteLine("The Thing is not a good movie. " +
                                                              "Go home and take a good hard look at your life.");
                                        };

            theStore.SendOutNotification("The Thing");

            // end of app
            Footer();
        }

Line 9 is where the damage is done, publishing a sacriligious message which should be disregarded at all costs.
Now, add the event keyword on the custom delegate, keep that member public and try and set it to a new delegate object as we just did above:

            public event NotifyDvdArrived notification;

Notice how … we can’t. You will get a compile error with a message along the lines of The event ‘DelegatesExplained.Program.DvdStore.notification’ can only appear on the left hand side of += or -= (except when used from within the type ‘DelegatesExplained.Program.DvdStore’

So, with encapsulation back in tact, we now have a safe way to subscribe handlers to, and removing them from, “event” delegates. This enables the delegate to be public (which it needs to be for subscribers), but protects it from being changed/written over.

Not bad, for one little word.
Get the code: