Sunday, 27 March 2016

Delegates and Event

Delegates have a few capabilities in C#: referencing methods, Dispatching multiple methods, asynchronous execution and event typing.

public delegate double Add(double num1, double num2);

A Delegate is just like a class , struct and interfaces. and its default access modifier is public and internal only.

Firing Events:
Events are type members that allows a type to notify other types of things that have happened.

A Button class, which is typically supplied by the UI technology you’re using.
2. An event member of the Button class, named Clicked.
3. The UI technology takes care of knowing when that Clicked event should fire. I’ll use a SimulateClick method in an upcoming code listing.
4. The event has a delegate type. Only methods that conform to the signature of that delegate type can assign to this delegate.
5. Your code defines a method to be called when that event fires.
6. The method you write must have a signature that matches the delegate type of the event. If the method signature doesn’t match the event delegate type signature, the compiler won’t let you assign that method to the delegate.


Basically, a delegate is just a wrapper around what would be a function pointer in C (or a list of function pointers)

An event is an even higher level abstraction that wraps the concept of a delegate together with methods to subscribe and unsubscribe a method to such delegates.
An event is a “property” that exposes an add and remove method (invoked via += and -= in code) to add/remove subscribers to a delegate list.

An event is a notification mechanism, based on delegates. The only thing it exposes publicly is a pair of methods (add/remove) to subscribe to or unsubscribe from the notification. A delegate type is used to define the signature of the handler methods, and the list of subscribers are (usually) stored internally as a delegate.

An Event declaration adds a layer of abstraction and protection on the delegate instance. This protection prevents clients of the delegate from resetting the delegate and its invocation list and only allows adding or removing targets from the invocation list.

"Suppose events didn't exist as a concept in C#/.NET. How would another class subscribe to an event?
Three options:
  1. public delegatevariable
  2. delegate variable backed by a property
  3. delegate variable with AddXXXHandler and RemoveXXXHandler methods
Option 1 is clearly horrible, for all the normal reasons we abhor public variables.
Option 2 is better, but allows subscribers to effectively override each other - it would be all too easy to write someInstance.MyEvent = eventHandler; which would replace any existing event handlers rather than adding a new one. In addition, you still need to write the properties.
Option 3 is basically what events give you, but with a guaranteed convention (generated by the compiler and backed by extra flags in the IL) and a "free" implementation if you're happy with the semantics that field-like events give you. Subscribing to and unsubscribing from events is encapsulated without allowing arbitrary access to the list of event handlers, and languages can make things simpler by providing syntax for both declaration and subscription."


to understand the differences you can look at this 2 examples
Exemple with Delegates (Action in this case that is a kind of delegate that doen't return value)
public class Animal
{
    public Action Run {get; set;}

    public void RaiseEvent()
    {
        if (Run != null)
        {
            Run();
        }
    }
}
to use the delegate you should do something like this
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
this code works well but you could have some weak spots.
For example if I write this
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
with the last line of code I had override the previous behaviors just with one missing + (I have used = instead of +=)
Another weak spot is that every class that use your Animal class can raise RaiseEvent just calling it animal.RaiseEvent().
To avoid this weak spots you can use events in c#.
Your Animal class will change in this way
public class ArgsSpecial : EventArgs
{
    public ArgsSpecial (string val)
    {
        Operation=val;
    }

    public string Operation {get; set;}
} 

public class Animal
{
    // Empty delegate. In this way you are sure that value is always != null 
    // because no one outside of the class can change it.
    public event EventHandler<ArgsSpecial> Run = delegate{} 

    public void RaiseEvent()
    {  
         Run(this, new ArgsSpecial("Run faster"));
    }
}
to call events
 Animale animal= new Animal();
 animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
 animal.RaiseEvent();
Differences:
  1. You aren't using a public property but a public field (with events the compiler protect your fields from unwanted access)
  2. Events can't directly be assigned. In this case you can't do the previous error that I have showed with overriding the behavior.
  3. No one outside of your class can raise the event.
  4. Events can be included in an interface declaration, whereas a field cannot
notes
EventHandler is declared as the following delegate:
public delegate void EventHandler (object sender, EventArgs e)
it takes a sender (of Object type) and event arguments. The sender is null if it comes from static methods.
You can use also EventHAndler instead this example that use EventHandler<ArgsSpecial>
refer here for documentation about EventHandler

No comments:

Post a Comment