Реализация событий C # (статьи против рефлектора) - PullRequest
4 голосов
/ 19 августа 2010

открытый класс 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);
        }
    }
}

Я ожидал, что компилятор C # будет переводить NewEvent так:

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);
    }
}

, но Reflector говорит, чтоэто реализовано так:

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);
    }
}

Пожалуйста, объясните мне, почему это так?

Ответы [ 3 ]

5 голосов
/ 19 августа 2010

Да: C # 4 сделал некоторые изменения в этой области , в основном. Это делает его потокобезопасным без блокировки. Это не единственное изменение - оно также меняет способ разрешения ссылок на подобные событиям внутри класса: + = и - = теперь проходят через биты «добавления» и «удаления», а не работают напрямую с вспомогательным полем.

Обратите внимание, что это изменение влияет на код, скомпилированный с помощью компилятора C # 4, даже на старых платформах; также есть изменения в блокировке, которые только влияют на код, скомпилированный для .NET 4, так как он использует новый метод (Monitor.TryEnter(object, out bool)).

2 голосов
/ 19 августа 2010

Ответ на этот вопрос во многом зависит от версии, которую вы используете.Это было усовершенствовано много за эти годы.Смотри http://blogs.msdn.com/b/cburrows/archive/2010/03/05/events-get-a-little-overhaul-in-c-4-part-i-locks.aspx

0 голосов
/ 19 августа 2010

То, что вы ожидаете, - это простая не поточно-безопасная реализация. Поле как синтаксис события всегда обеспечивает потокобезопасный синтаксис (отсюда и версия рефлектора). Обратитесь к этому artcile для понимания событий и того, как они реализуются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...