[英]C# Delegates and method signatures
從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
。
也許我有點誤解了代表,如果有人可以解釋我要去哪里錯了,我將不勝感激。
代表就像一堂課。 一個事件就像一個財產。 當您在類中聲明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();
}
實際上,簽名是相同的。 在.NET中,事件是通過委托實現的。
public event AlarmEventHandler Alarm;
因此,以上代碼實際上是由編譯器編譯為:
private AlarmEventHandler handler;
public event AlarmEventHandler Alarm
{
add { handler += value; }
remove { handler -= value; }
}
因此,事件實際上使用相同的AlarmEventHandler
委托。
一個事件只是一個委托。 委托本身只能從類內部訪問。 從外部,只能為事件添加和刪除功能,您只能執行以下操作:
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);
}
可以將以基類為參數(非引用)的函數轉換為以派生類為參數的委托。 這是因為只要使用了采用派生類的函數,就可以安全地替換采用base的函數。
void TakesObject(object o)
{
...
}
Action<string> myAction=TakesObject;
您只能通過傳入字符串來調用myAction。 並且由於每個字符串都是對象,因此TakesObject的合同已得到履行。
在您的情況下是AlarmEventArgs
因為每個AlarmEventArgs
也是一個EventArgs
。 因此,事件處理程序的合同要求沒有事件所使用的委托類型的合同保證嚴格。
這稱為協方差和反方差。 您在返回類型中具有協方差,而在參數中具有相反方差。
在MSDN上查看此文章:
在委托中使用方差(C#和Visual Basic)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.