[英]Why should I check for null before I invoke the custom event?
這兩個代碼示例之間用於調用事件有什么區別?
樣品1
public void OnDataChanged()
{
if (DataChanged != null)
{
DataChanged(this);
}
}
樣本2
DataChanged.Invoke(this);
我應該何時使用每種方法來調用自定義事件? 為什么有時我嘗試使用DataChanged.Invoke(this)
調用事件時會得到NullReferenceException,但是當我將事件調用轉換為示例1中的方法時, DataChanged
永遠不會變為null?
OnXYZ
方法應始終遵循以下形式:
public void OnXYZ()
{
var evt = XYZ;
if (evt != null)
evt(sender, e); // where to get e from differs
}
這種形式有幾個原因:
if evt != null
檢查確保我們不會嘗試調用null
委托。 如果沒有人將事件處理程序連接到事件,就會發生這種情況。 evt
,我們可以在檢查非null之后安全地調用它,因為沒有人可以在if
但在調用之前改變它。 e
傳遞的內容有所不同,如果需要使用參數傳遞EventArgs
后代,有兩種方法:
public void OnXYZ(string p)
{
var evt = XYZ;
if (evt != null)
evt(sender, new SomeEventArgs(p));
}
或者更常見的是:
public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}
這個語法:
evt(sender, e);
只是一種不同的寫作方式:
evt.Invoke(sender, e);
另請注意,在您的類外部,事件是一個事件,您只能從中add
或remove
事件處理程序。
在您的類的內部,事件是委托,您可以調用它,檢查目標或方法,遍歷訂閱者列表等。
此外,在C#6中引入了一個新的運算符, ?.
- Null條件運算符 - 它基本上是if not-null, dereference
縮寫,可以縮短這個方法:
public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}
進入這個:
public void OnXYZ(SomeEventArgs e)
{
XYZ?.Invoke(sender, e);
}
可以通過使用表達身體成員進一步縮短:
public void OnXYZ(SomeEventArgs e) => XYZ?.Invoke(sender, e);
請注意,不能寫這個:
XYZ?.(sender, e);
所以你必須在這種情況下使用Invoke
。
當我將事件調用轉換為示例1中的方法時,DataChanged永遠不會變為空
然后你只是看兩種不同的場景。
如果你沒有聲明像public event EventHandler YourEvent = delegate { };
那樣的public event EventHandler YourEvent = delegate { };
,然后YourEvent
為null
直到某些消費者訂閱它。
如果沒有訂閱DataChanged它將被設置為null,所以當你嘗試執行DataChanged.Invoke(this)時,你會得到一個NullRefException,因為它真的試圖做null.Invoke(this)。 附加if(DataChanged!= null)的原因是為了避免在沒有人訂閱該事件時發生這種情況。
我不相信當你使用Sample 1 DataChanged永遠不會為null時,它永遠不會到達.Invoke來拋出異常。 如果沒有人訂閱,它將始終為null。
您確定,在示例1中, DataChanged
永遠不會為空嗎? 或者你只是沒有得到NullReference異常(因為你檢查if
語句中的DataChanged
是否為空 )?
讓我們從基礎開始。 活動是一種特殊的代表。 當你調用DataChanged(this)和DataChanged.Invoke(this)時,它是一樣的。 為什么? 因為它編譯成同樣的東西。 總而言之, DataChanged(this)
只是調用DataChanged.Invoke(this)
的簡寫。
現在,為什么我們需要檢查空引用(如示例1中所示)。 基本上,當您調用事件時,您將調用訂閱此事件的所有方法(例如, DataChanged += someEventHandler
)。 如果沒有人訂閱此事件,它將具有null
值。 沒有分配方法來處理此事件。 換句話說:事件處理程序為null。
這就是為什么在調用事件之前檢查null是一個好習慣。
一個例子:
public void OnAbc(){
var data=Abc;
if(!String.IsNullOrEmpty(data))
Abc(sender,e);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.