2017-02-12 37 views
3

這2個樣本是否相同?可以將舊樣式提升替換爲Invoke和空傳播嗎?事件引發空傳播的線程安全

OLD:

public event EventHandler<MyEventArgs> MyEvent; 
    protected virtual void OnMyEvent(MyEventArgs args) 
    { 
     EventHandler<MyEventArgs> handler = this.MyEvent; 
     if (handler != null) 
      handler(this, args); 
    } 

新:

public event EventHandler<MyEventArgs> MyEvent; 
    protected virtual void OnMyEvent(MyEventArgs args) 
    { 
     this.MyEvent?.Invoke(this, args); 
    } 

空檢查是很重要的,但它是明確的。什麼是附加變量?
null-propogation如何在內部工作?事件是線程安全的嗎?

P.S.關於事件的線程安全的,你可以在這裏閱讀:
C# Events and Thread Safety

+0

相關:https://codeblog.jonskeet.uk/2015/01/30/clean-event-handlers-invocation-with-c-6/ – VMAtm

+0

此外,俄語鏈接:https://habrahabr.ru/後/ 89529 /和https://habrahabr.ru/post/240385/ – VMAtm

+0

這是不重複..至少線程安全是在這個問題的具體主題..並在以前的帖子回答說一些奇怪的「編譯器生成代碼只評估PropertyChanged一次,將結果保存在臨時變量中「..它對線程安全沒有任何幫助。只有複製纔是事實!這是由@eocron調查的。所以它有所不同。要理解究竟發生了什麼,從這篇文章中得到答案比上一篇更好。 – Maxim

回答

6

鑑於此代碼:

static void Main(string[] args) 
    { 
     var a = new Random(1).Next() > 0 ? new object() : null; 
     var b = a?.GetHashCode(); 
     Console.WriteLine(b); 
    } 

這是我在行IL表示,其中一元運算符稱爲在釋放模式(VS 2015)見:

IL_0016: dup   
IL_0017: brtrue.s  IL_0025 

... //nothing iteresting, just setting null to 'a' and skip IL_0025 area 

IL_0025: callvirt  instance int32 [mscorlib]System.Object::GetHashCode() 

讓我解釋一下:

  • DUP - 是命令,該命令的副本上堆電流值到新的一個放置在該堆(在這種情況下,它被簡單地複製「A」的值)
  • brtrue.s - 將控制轉移到地址,如果值上堆棧是真/ NOTNULL /非零(截至目前值是「A」的副本 - 它是線程安全的使用它)

所以,回答你的問題是:是,它是線程-safe使用monadic操作符,因爲它是通過副本操作的。

+0

感謝IL的工作!現在很清楚......這將是一個副本。 – Maxim

+0

這個版本在理論上不會中斷,但仍然不是線程安全的解決方案。在實踐中,它是好的級別的解決方案 – VMAtm

+0

事件本身的提升是線程安全的......任何其他代碼的線程安全是無關的。 – Maxim