2

ILSpyを使用してアセンブリを逆コンパイルしましたが、特に1つのクラスが注目されました。

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にあまり詳しくありません、ところで...

(補足:アプリケーションはマルチスレッドであり、明らかにネットワーキングを利用しています。)

4

1 に答える 1

9

これは、コンパイラによって生成された新しいイベントハンドラコードです。C#4で導入されました(C#3のバージョンは異なります)

Interlocked.CompareExchangeは、最初の引数を3番目の引数と比較し、それらが等しい場合は、最初の引数を2番目の引数に置き換えます。これはスレッドセーフな操作です。ループは、変数eventHandler2を割り当てた後、チェックする前に、別のスレッドがこのデリゲートを変更する場合に使用されます。この場合、Interlocked.CompareExchangeは交換を実行せず、ループ条件はtrueと評価されず、次の試行が行われます。

C#3は、イベントハンドラーで単純なコードを生成しました。

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

パフォーマンスが低下し、デッドロックが発生する可能性があります。

このテーマに関する一連の素晴らしい記事があります。

イベントはC#4で少しオーバーホールされます

イベントはC#4、パートIIで少しオーバーホールされます

于 2013-03-26T20:03:58.930 に答える