Difference between events and delegates and its re

2019-01-02 14:41发布

I don't see advantages of using events over delegates, other than being syntactical sugar. Perhaps I am misunderstanding, but it seems that event is just a placeholder for delegate.

Would you explain to me the differences and when to use which? What are the advantages and disadvantages? Our code is heavily rooted with events, and I want to get to the bottom of it.

When would you use delegates over events and vice versa? Please state your real world experience with both, say in the production code.

10条回答
裙下三千臣
2楼-- · 2019-01-02 15:21

Events are syntactical sugar. They are delicious. When I see an event, I know what to do. When I see a delegate, I'm not so sure.

Combining events with interfaces (more sugar) makes for a mouth watering snack. Delegates and pure virtual abstract classes are much less appetizing.

查看更多
余生无你
3楼-- · 2019-01-02 15:24

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
    {
       public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it

       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

查看更多
路过你的时光
4楼-- · 2019-01-02 15:25

The keyword event is a scope modifier for multicast delegates. Practical differences between this and just declaring a multicast delegate are as follows:

  • You can use event in an interface.
  • Invocation access to the multicast delegate is limited to the declaring class. The behaviour is as though the delegate were private for invocation. For the purposes of assignment, access is as specified by an explicit access modifier (eg public event).

As a matter of interest, you can apply + and - to multicast delegates, and this is the basis of the += and -= syntax for the combination assignment of delegates to events. These three snippets are equivalent:

B = new EventHandler(this.MethodB);
C = new EventHandler(this.MethodC);
A = B + C;

Sample two, illustrating both direct assignment and combination assignment.

B = new EventHandler(this.MethodB);
C = new EventHandler(this.MethodC);
A = B;
A += C;

Sample three: more familiar syntax. You are probably acquainted with the assignment of null to remove all handlers.

B = new EventHandler(this.MethodB);
C = new EventHandler(this.MethodC);
A = null;
A += B;
A += C;

Like properties, events have a full syntax that no-one ever uses. This:

class myExample 
{
  internal EventHandler eh;

  public event EventHandler OnSubmit 
  { 
    add 
    {
      eh = Delegate.Combine(eh, value) as EventHandler;
    }
    remove
    {
      eh = Delegate.Remove(eh, value) as EventHandler;
    }
  }

  ...
}

...does exactly the same as this:

class myExample 
{
  public event EventHandler OnSubmit;
}

The add and remove methods are more conspicuous in the rather stilted syntax that VB.NET uses (no operator overloads).

查看更多
长期被迫恋爱
5楼-- · 2019-01-02 15:28

Although I've got no technical reasons for it, I use events in UI style code, in other words, in the higher levels of the code, and use delegates for logic that lays deeper in the code. As I say you could use either, but I find this use pattern to be logically sound, if nothing else, it helps document the types of callbacks and their hierarchy too.


Edit: I think the difference in usage patterns I have would be that, I find it perfectly acceptable to ignore events, they are hooks/stubs, if you need to know about the event, listen to them, if you don't care about the event just ignore it. That's why I use them for UI, kindof Javascript/Browser event style. However when I have a delegate, I expect REALLY expect someone to handle the delegate's task, and throw an exception if not handled.

查看更多
登录 后发表回答