开发者

C# Delegates and method signatures

From MSDN:

Any method that matches the delegate's signature, which consists of the return type and parameters, can be assigned to the delegate.

So how is this possible:

public delegate void AlarmEventHandler(object sender, EventArgs e);
public event AlarmEventHandler Alarm;

protected virtual void OnAlarm(EventArgs e)
        {
            AlarmEventHandler开发者_如何学Python handler = Alarm;
            if (handler != null)
            {
                // Invokes the delegates.
                handler(this, e);
            }
        }

delegate AlarmEventHander and event AlarmEventHandler have different signatures yet handler can be assigned to Alarm.

Perhaps I'm mis-understanding delegates somewhat, and I would be very grateful if someone could explain where I'm going wrong.


A delegate is like a class. An event is like a property. When you declare an event in a class, you declare the type of event it is. In this case, AlarmEventHandler, which is an inner class of the top-level class this is a part of.

In the OnAlarm method, you get the instance of the AlarmEventHandler class that has been assigned to the event, and invoke it.

To clear things up, your code above is similar to this, using normal classes & references:

public class InnerClass {
    public void MyMethod() { /* ... */ }
}

public InnerClass MyProperty { get; set; }

protected virtual void CallMyMethod() {
    InnerClass cls = MyProperty;
    if (cls != null)
        cls.MyMethod();
}


Actually the signatures are the same. In .NET events are implemented with delegates.

public event AlarmEventHandler Alarm;

So above code is actually compiled by compiler as:

private AlarmEventHandler handler;

public event AlarmEventHandler Alarm
{
    add { handler += value; }
    remove { handler -= value; }
}

So event actually uses the same AlarmEventHandler delegate.


  1. You are mixing delegates and events. While events are dependant on delegates, they are difference concepts completly. So should be taken separately.
  2. Delegate is like type definition. Place where you use this delegate is like variable or property.
  3. Event makes this delegate behave differently from the outside. Signature is still same.


An event is just a delegate. The delegate itselft can only be accessed from inside the class. From the outside, only add and remove functionality for the event is possible to you can only do this:

myAlarm.Alarm+=new AlarmEventHandler(callPolice);
// or
myAlarm.Alarm-=new AlarmEventHandler(callPolice);

But from the inside of the class, Alarm is just a delegate of type AlarmEventHandler so you can do what your code shows:

        AlarmEventHandler handler = Alarm;
        if (handler != null)
        {
            // Invokes the delegates.
            handler(this, e);
        }


A function which takes a base-class as (non reference) parameter can be converted to a delegate that takes a derived class as parameter. This is because the function that takes base can be safely substituted where-ever a function that takes a derived class is used.

void TakesObject(object o)
{
...
}

Action<string> myAction=TakesObject;

You can call myAction only by passing in a string. And since every string is an object the contract for TakesObject is fulfilled.

In your case is works because every AlarmEventArgs is an EventArgs too. So the contract requirements of your eventhandler are less strict than the contract guarantees of the delegate type used by the event.

This is called co- and contra-variance. You have co-variance in return-types, and contra variance in parameters.

Check this article on MSDN:
Using Variance in Delegates (C# and Visual Basic)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜