tags:

views:

69

answers:

3

Hi, I wrote some code:

public class EventsType
{
    public event EventHandler<MyEventArgs<Object>> 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?

+2  A: 

The answer to this question very much depends on the version you're using. It has been refined a lot over the years. See http://blogs.msdn.com/b/cburrows/archive/2010/03/05/events-get-a-little-overhaul-in-c-4-part-i-locks.aspx

Daniel Earwicker
+2  A: 

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)).

Jon Skeet
A: 

What you are expecting is a simple non thread safe implementation. The field like event syntax always provide thread-safe syntax (hence the reflector version). Refer this artcile for understanding events & how they get implemented.

VinayC