问题
I decompiled an assembly using ILSpy, and one class in particular got my attention:
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...
}
}
}
Further in the code, seems like private delegate is used to fire an actual event:
if (something != null && somethingElse != 0)
{
this.someEvent(this, new CustomEventArgs(someArg));
}
The question: Can someone guess what could be the idea behind this custom accessors, assuming that some "compile/decompile magic" didn't take place? I'm not much familiar with IL, btw...
(Side note: the application is multi-threaded and utilizes networking, obviously.)
回答1:
This is a new event handler code generated by compiler. It was introduced in C# 4 (C# 3 version was different)
Interlocked.CompareExchange compares first argument with third, and if they are equal, replaces first argument with second. This is a thread-safe operation. Loop is used for a case when after assigning a variable eventHandler2 and before check, another thread changes this delegate. In this case, Interlocked.CompareExchange does not perform exchange, loop condition does not evaluate to true and next attempt is made.
C# 3 generated simple code in event handlers:
add { lock(this) { changed = changed + value; } }
Which had lower performance and could introduce deadlocks.
There is a great series of articles on this subject:
Events get a little overhaul in C# 4
Events get a little overhaul in C# 4, Part II
来源:https://stackoverflow.com/questions/15646155/decompiled-assembly-unusual-code