2013-03-26 210 views
2

我反編譯使用ILSpy組件,特別是一類了我的注意:反編譯彙編 - 異常代碼

public class CustomTextStream : NetworkStream 
{ 
    private EventHandler<CustomEventArgs> someEvent; 
    public event EventHandler<CustomEventArgs> SomePublicEvent 
    { 
     add 
     { 
      EventHandler<CustomEventArgs> eventHandler = this.someEvent; 
      EventHandler<CustomEventArgs> eventHandler2; 
      do 
      { 
       eventHandler2 = eventHandler; 
       EventHandler<CustomEventArgs> value2 = 
        (EventHandler<CustomEventArgs>)Delegate.Combine(eventHandler2, value); 
       eventHandler = 
        Interlocked.CompareExchange<EventHandler<CustomEventArgs>>(
        ref this.someEvent, value2, eventHandler2); 
      } 
      while (eventHandler != eventHandler2); 
     } 
     remove 
     { 
      // similar stuff... 
     } 
    } 
} 
代碼

而且,似乎是私人委託用於火災實際事件:

if (something != null && somethingElse != 0) 
{ 
    this.someEvent(this, new CustomEventArgs(someArg)); 
} 

問題:假設某些「編譯/反編譯魔法」沒有發生,有人可以猜測這個自定義訪問器背後的想法是什麼嗎?我沒有太多熟悉IL,順便說一句...

(旁註:應用是多線程的,利用網絡,很明顯。)

+0

看起來像第一眼默認代碼 - 正常的「事件」其實是一些接近這個代碼。考慮嘗試使用事件而不是反編譯來創建代碼。 – 2013-03-26 19:58:06

+1

我看到奇怪的東西,像這樣產生的混淆器只是爲了混淆你。 – NickD 2013-03-26 19:58:59

+0

@Alexei Levenkov我已經做到了。我沒有得到相同的結果。 「正常」反編譯事件中唯一的事情是'Delegate.Combine()'部分 – Less 2013-03-26 19:59:45

回答

8

這是由編譯器生成一個新的事件處理程序代碼。它在C#4中引入(C#3版本不同)

Interlocked.CompareExchange將第一個參數與第三個參數進行比較,如果它們相等,則用第二個參數替換第一個參數。這是一個線程安全的操作。循環用於在分配變量eventHandler2之後並在檢查之前,另一個線程更改此代理。在這種情況下,Interlocked.CompareExchange不執行交換,循環條件不計算爲真,並進行下一次嘗試。

C#3生成的事件處理程序簡單的代碼:

add { lock(this) { changed = changed + value; } } 

其中有較低的性能,並可能導致死鎖。

有一個偉大的系列關於這個問題的文章:

Events get a little overhaul in C# 4

Events get a little overhaul in C# 4, Part II