来自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
。
也许我在某种程度上误解了代表,如果有人能解释我哪里出错了,我将非常感激。
答案 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)
答案 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)