C#代理和方法签名

时间:2011-01-31 11:10:12

标签: c# delegates

来自MSDN

  

任何与委托相匹配的方法   签名,由...组成   返回类型和参数,即可   分配给代表。

那怎么可能呢?

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

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

委托AlarmEventHander和事件AlarmEventHandler具有不同的签名,但handler可以分配给Alarm

也许我在某种程度上误解了代表,如果有人能解释我哪里出错了,我将非常感激。

5 个答案:

答案 0 :(得分:7)

代表就像一个班级。事件就像一个财产。在类中声明event时,声明事件的类型。在这种情况下,AlarmEventHandler,它是顶级类的内部类,这是它的一部分。

OnAlarm方法中,您将获得已分配给该事件的AlarmEventHandler类的实例,并将其调用。

为了清理问题,上面的代码与此类似,使用普通类&引用:

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

public InnerClass MyProperty { get; set; }

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

答案 1 :(得分:2)

实际上签名是一样的。在.NET中,事件是通过代理实现的。

public event AlarmEventHandler Alarm;

所以上面的代码实际上是由编译器编译的:

private AlarmEventHandler handler;

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

因此事件实际上使用相同的AlarmEventHandler委托。

答案 2 :(得分:0)

  1. 您正在混合代表和活动。虽然事件依赖于代理,但它们完全是差异概念。所以应该单独进行。
  2. 委托类似于类型定义。您使用此委托的地方就像变量或属性一样。
  3. 事件使得此委托的行为与外部不同。签名仍然相同。

答案 3 :(得分:0)

事件只是一个代表。代表itselft只能从课堂内访问。 从外部来看,只有添加删除功能才可以执行此操作:

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

但是从类的内部来看,Alarm只是AlarmEventHandler类型的委托,因此您可以执行代码显示的内容:

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

答案 4 :(得分:-3)

将基类作为(非引用)参数的函数可以转换为将派生类作为参数的委托。这是因为使用base的函数可以安全地替换使用派生类的函数。

void TakesObject(object o)
{
...
}

Action<string> myAction=TakesObject;

您只能通过传入字符串来调用myAction。因为每个字符串都是一个对象,所以TakesObject的合同就完成了。

在你的情况下是有效的,因为每个AlarmEventArgs也是EventArgs。因此,事件处理程序的合同要求不如事件使用的委托类型的合同保证严格。

这称为共方差和反方差。你有回归类型的协方差和参数的反差。

在MSDN上查看这篇文章:
Using Variance in Delegates (C# and Visual Basic)