public class EventsType
{
public event EventHandler> NewEvent;
public void SmthHappened(string data)
{
MyEventArgs<Object> eventArgs = new MyEventArgs<Object>(data);
OnNewEvent(eventArgs);
}
private void OnNewEvent(MyEventArgs<Object> eventArgs)
{
EventHandler<MyEventArgs<Object>> tempEvent = NewEvent;
if (tempEvent != null)
{
tempEvent(this, eventArgs);
}
}
}
I expected that the C# compiler will translate the NewEvent like this:
private EventHandler<MyEventArgs<object>> _newEvent;
public event EventHandler<MyEventArgs<object>> NewEvent
{
[MethodImpl(MethodImplOptions.Synchronized)]
add
{
_newEvent = (EventHandler<MyEventArgs<object>>)Delegate.Combine(_newEvent, value);
}
[MethodImpl(MethodImplOptions.Synchronized)]
remove
{
_newEvent = (EventHandler<MyEventArgs<object>>)Delegate.Remove(_newEvent, value);
}
}
, but the Reflector says that it is implemented this way:
public event EventHandler<MyEventArgs<object>> NewEvent
{
add
{
EventHandler<MyEventArgs<object>> handler2;
EventHandler<MyEventArgs<object>> newEvent = this.NewEvent;
do
{
handler2 = newEvent;
EventHandler<MyEventArgs<object>> handler3 = (EventHandler<MyEventArgs<object>>) Delegate.Combine(handler2, value);
newEvent = Interlocked.CompareExchange<EventHandler<MyEventArgs<object>>>(ref this.NewEvent, handler3, handler2);
}
while (newEvent != handler2);
}
remove
{
EventHandler<MyEventArgs<object>> handler2;
EventHandler<MyEventArgs<object>> newEvent = this.NewEvent;
do
{
handler2 = newEvent;
EventHandler<MyEventArgs<object>> handler3 = (EventHandler<MyEventArgs<object>>) Delegate.Remove(handler2, value);
newEvent = Interlocked.CompareExchange<EventHandler<MyEventArgs<object>>>(ref this.NewEvent, handler3, handler2);
}
while (newEvent != handler2);
}
}
Please, smb explain me why is it so?
Yup: C# 4 has made some changes in this area, basically. It makes it thread-safe without locking. That’s not the only change – it also changes how references to field-like events within the class are resolved: += and -= now go through the “add” and “remove” bits rather than working directly with the backing field.
Note that this change affects code compiled with the C# 4 compiler even against older frameworks; there are also changes to locking which only affect code compiled against .NET 4, as it uses a new method (
Monitor.TryEnter(object, out bool)).