Thursday 10 December 2015

The Anonymous from C#

Going anonymous

Prior to .NET 2.0, the only way to declare a delegate was to use named methods. While this was a way but it was not that very fluent. The programmer has to create a new method that conforms to the signature of the delegate and then pass it to the delegate. This is fine when you write small programs but as the project grows, it begins to cramp up the maintenance process. If a fellow programmer has to fix a bug then first a search for the method in the source code has to be done following the fix up process. It is definitely a time consuming process.


Enter anonymous 

.NET 2.0 introduced the concept of the anonymous method which powers the developer to define the method inline to the call.

 public delegate int MathOperationDelegate(int x, int y);
    class Program
    {
        static void Main(string[] args)
        {
            MathOperationDelegate operationDelegate = null;
 
 
            //No need to create a seperate method
            operationDelegate += delegate(int x, int y)
            {
                return x + y;
            };
 
            operationDelegate += delegate(int x, int y)
            {
                return x - y;
            };
            operationDelegate += delegate(int x, int y)
            {
                return x * y;
            };
            operationDelegate += delegate(int x, int y)
            {
                return x / y;
            };
 
 
            //Prior to .NET 2
            //Methods have to be explicitely created, prior to the Invoke
            operationDelegate += OnAddMathOperationDelegate;
 
            operationDelegate += OnMulMathOperationAction;
 
            operationDelegate += OnDivMathOperationAction;
 
            operationDelegate += delegate(int x, int y)
            {
                return x / y;
            };
 
 
           var result = operationDelegate(12, 12);
           Console.WriteLine(  result );
        }
 
        private static int OnDivMathOperationAction(int x, int y)
        {
            return x*y;
        }
 
        private static int OnMulMathOperationAction(int x, int y)
        {
            return x - y;
        }
 
        private static int OnAddMathOperationDelegate(int x, int y)
        {
            return x + y;
        }
 
    }


The above program shows both named and anonymous method.
From the first observation, anonymous methods are easy to create and debug. Maintenace is much simpler. 

By using anonymous methods, you reduce the coding overhead in instantiating delegates because you do not have to create a separate method. For example, specifying a code block instead of a delegate can be useful in a situation when having to create a method might seem an unnecessary overhead.


la la al

Sunday 4 October 2015

The Delegates of C#

The Delegates of C#

"A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance." - MSDN

Hello Delegates :)

When I first started learning C# about close to 2 years now I was introduced to delegates and at first glance it looked quiet easy to me but then slowly things changed as I was introduced to all sorts of nasty lambdas in LINQ and Unit testing framework and actually they are all over the place. So I took my time out to learn these these little pearls.

So lets see what these good things are how they do what they do.

Introduction:

In simplest term delegates are type(class)that point to a function and when invoked calls the function/s they point to.

Foo meets Bar
    Lets see a real world analogy. Consider a scenario where a manager Foo is asked to prepare a presentation but due to time constraint and other priorities he is unable to do it. So what should he do now? He can't leave that work hanging so he asks his sub-ordinate Bar to do the presentation for him. In other words he just delegates the work to his co-worker who is qualified enough to do that work. The presentation is completed and everyone is happy with Foo. Bar has done his work successfully as asked. Days pass and just before christmas manager Foo is again asked to do a presentation but with different theme and concept. Again he is busy so he asks his co-ordinate Bar to help him out. He explains him what has to be done and delegates the work. Yay work is done and everyone is happy!

The story has a happy ending but notice the bold words in the story above like qualified, explains and delegates. Now lets see how Mr C# meets his delegate friend.

So putting it in formal way delegates are type that point to functions that follow specific signatures as defined by the delegates. When invoked the delegates invoke all the functions in their invocation list.

Enough of storytelling and talking lets see some code shall we?


public delegate void MyDelegate(int x, int y);

The delegate in C# is created using deleagate keyword. Nothing fancy here. Then comes the delegate name and the signature of the function to which it can point to. The signature of the function is important because it decides if the delegate can point to that function (add that function in its invocation list. We will see this in a moment).Remember the word qualified from the Foo-Bar story above? So this is the signature that makes all the functions qualified for getting added into the invocation list of the delegate. So in the above example of MyDelegate we have created MyDelegate delegate which can point to all the functions that take two int and return void. For example MyDelegate can point to following functions 


        public void DoSomething(int a, int b)
        {
           //do something please 
        }
 
        public void Apple(int a, int b)
        {
            //This method also takes two int and returns void 
        }
 
        public void Mango(int a, int b)
        {
            //name of the method is irrelevent
        }


However it cannot point to following function because they don't have the same signature as defined by the delegate MyDelegate.
        public bool ValidateCustomer(IValidateCustomer customer)
        {
          //This method does not retun void and it does not take two ints
          //So this MyDelegate cannot point to it.
            
        }
Note : Methods do not have to match the delegate type exactly. We will touch on this in detail later in this post
Hopefully you must have got what delegates are how to create them. Now lets see how a delegate can point to a valid method and what is invocation list.


Our Compiler friend

Simple delegate delaration


    public delegate void MyDelegate(int x, int y);
    class DelegateLearning
    {
    }


Decompiled version (ILSpy)


    .class public auto ansi sealed Learning.MyDelegate
 extends [mscorlib]System.MulticastDelegate
     {
 // Methods
 .method public hidebysig specialname rtspecialname 
  instance void .ctor (
   object 'object',
   native int 'method'
  ) runtime managed 
 {
 } // end of method MyDelegate::.ctor
 
 .method public hidebysig newslot virtual 
  instance void Invoke (
   int32 x,
   int32 y
  ) runtime managed 
 {
 } // end of method MyDelegate::Invoke
 
 .method public hidebysig newslot virtual 
  instance class [mscorlib]System.IAsyncResult BeginInvoke (
   int32 x,
   int32 y,
   class [mscorlib]System.AsyncCallback callback,
   object 'object'
  ) runtime managed 
 {
 } // end of method MyDelegate::BeginInvoke
 
 .method public hidebysig newslot virtual 
  instance void EndInvoke (
   class [mscorlib]System.IAsyncResult result
  ) runtime managed 
 {
 } // end of method MyDelegate::EndInvoke// end of class LinqLearning.MyDelegate


So lets see what is happening here. First we have created a delegate and then we have decompiled the same using ILSpy
If we look closesly we see that behind the scenes our compiler friend is doing a lot of work for us. delegate keyword is actually converted to a corresponding class by compiler of the same name. The class then inherits from System.MulticastDelegate. So a delegate is nothing but a class that inherits from System.MulticastDelegate which in turns inherit from System.Delegate.


"A MulticastDelegate has a linked list of delegates, called an invocation list, consisting of one or more elements. When a multicast delegate is invoked, the delegates in the invocation list are called synchronously in the order in which they appear." - MSDN

Invocation List

The Invocation list of a delegate is an ordered set of delegates in which each element of the list invokes exactly one of the methods represented by the delegate. An invocation list can contain duplicate methods. During an invocation, methods are invoked in the order in which they appear in the invocation list. A delegate attempts to invoke every method in its invocation list; duplicates are invoked once for each time they appear in the invocation list. Delegates are immutable; once created, the invocation list of a delegate does not change.

Adding a method to invocation list is easy

  1. Pass method to the ctor of the Delegate type
  2. Assign method to the delegate 
  3. Use MulticastDelegate.Combine method to add multiple methods 
  4. += is the short hand for Combine


Following program will make it clear  :


namespace DelegateLearning
{
    public delegate int MathematicalOperationDelegate(int x, int y); //declare
 
    public enum MathematicalOperation
    {
      Add,
      Substract,
      Multiply,
      Divide
    }
 
    class DelegateLearning
    {
        private readonly MathematicalOperationDelegate _mathematicalOperationDelegate;
 
        public DelegateLearning(MathematicalOperation operation)
        {
            switch (operation)
            {
                case MathematicalOperation.Add:
                    _mathematicalOperationDelegate += new MathematicalOperationDelegate(AddOperationTarget); //Adding to invocation list
                    break;
 
                case MathematicalOperation.Substract:
                    _mathematicalOperationDelegate += new MathematicalOperationDelegate(SubOperationTarget); //Adding to invocation list
                    break;
 
                case MathematicalOperation.Multiply:
                    _mathematicalOperationDelegate += new MathematicalOperationDelegate(MultiplyOperationTarget); //Adding to invocation list
                    break;
 
                case MathematicalOperation.Divide:
                    _mathematicalOperationDelegate += new MathematicalOperationDelegate(DivideOperationTarget); //Adding to invocation list.
                    break;
            }
        }
 
        public int PerformMathematicalOperation(int x, int y , MathematicalOperation operation)
        {
            int result = 0;
            if (_mathematicalOperationDelegate != null)
            {
                result = _mathematicalOperationDelegate(x, y); //Invoke
                Console.WriteLine( "Result : " + result);
            }
 
            return result;
        }
 
        private int AddOperationTarget(int x, int y)
        {
            return x + y;
        }
 
        private int SubOperationTarget(int x, int y)
        {
            return x - y;
        }
 
        private int MultiplyOperationTarget(int x, int y)
        {
            return x * y;
        }
 
        private int DivideOperationTarget(int x, int y)
        {
            return x / y;
        }
    }
 
}

In Main :


public static void Main() {
  var learning = new global::DelegateLearning.DelegateLearning(MathematicalOperation.Add);
  var result = learning.PerformMathematicalOperation(12, 12);
  Console.WriteLine(  result );
}

Output : 24

Lets take our time to understand what is happening and why its doing what it is doing. We start by declaring a delegate MathematicalOperationDelegate. This delegate will point to any function/s which takes two int and return int.
Next we create a class DelegateLearning which has one parametrized constructor which takes enum MathematicalOperation. Based on the enum passed, corresponding method will be added to the invocation list of the MathematicalOperationDelegate. 
+= can be used to add a method to the invocation list of any delegate. This is shorthand for the public static Delegate Combine(params Delegate[] delegates); method in MulticastDelegate class.

Our class declares a method PerformMathematicalOperation invokes the delegate as result = _mathematicalOperationDelegate(x, y); //Invoke
At this point all the methods present in the invocation list of the delegate will be executed one by one with parameter value of x and y.
Please note that the null check is required before invoking the delegate otherwise NullReferenceException will be thrown.



But ... Why all this?


The question in your mind will be why all this is required. We could have called methods directly and could have got the same result. Yes you are right, maybe in this case you could have done it. But hey there is Hello World in every language!


The caller can decide the method @ runtime

The advantage of delegates is that now caller gets opportunity to decide the method implementation at runtime. Its quiet similar to Interfaces. So if a developer is creating an API for Mathematical operation, he can just provide a delegate with signature and user of the API can decide his/her own implementation. For example in the above example I can create a method that takes two int and provide my custom implementation. My DelegateLearning class doesn't have to worry about the calulation alogrithm. It therefore provides and better seperation of concern.

Delegates are useful when:

  1. A single method is being called.
  2. A class may want to have multiple implementations of the method specification.
  3. It is desirable to allow using a static method to implement the specification.
  4. An event-like design pattern is desired.
  5. The caller has no need to know or obtain the object that the method is defined on.
  6. The provider of the implementation wants to "hand out" the implementation of the specification to only a few select components.
  7. Easy composition is desired.


Before we end:


Variance in Delegates

  1. Covariance permits a method to have return type that is more derived than that defined in the delegate.
  2. Contravariance permits a method that has parameter types that are less derived than those in the delegate type.

    class Person { }
    class Man : Person { }
 
    class Program
    {
        // Define the delegate.
        public delegate Person HandlerMethod();
 
        public delegate Person HandlerMehtod2(Man p);
 
        public static Person PersonHandler()
        {
            return null;
        }
 
        public static Man ManHandler()
        {
            return null;
        }
 
        public static Man ManHandler2(Person person)
        {
            return null;
        }
 
        static void Test()
        {
            HandlerMethod handlerPerson = PersonHandler;
 
            // Covariance enables this assignment.
            HandlerMethod handlerMan = ManHandler;
 
            //Contravariance enables this assignment.
            HandlerMehtod2 handlerMehtod = ManHandler2;
            ManHandler2(new Man());
        }
 
 
 
    }


This example demonstrates how delegates can be used with methods that have return types that are derived from the return type in the delegate signature. The data type returned by ManHandler is of type Man, which derives from Person type that is defined in the delegate.





This post covered delegates and in general. In next post I will cover anonymous methods and Lambdas which makes delegates more fun!

I hope you liked it. Do correct me if I have made any mistakes.
Till then next time happy coding :)

References:
https://msdn.microsoft.com/en-in/library/aa288459(v=vs.71).aspx