Подтвердить что ты не робот

Вопрос относительно значения/ссылочного типа событий

В MSDN я нашел следующее:

public event EventHandler<MyEventArgs> SampleEvent;

public void DemoEvent(string val)
{
// Copy to a temporary variable to be thread-safe.
    EventHandler<MyEventArgs> temp = SampleEvent; 

Это ссылка?
Если это так, я не понимаю его значения, как когда SampleEvent стал нулевым, так и temp

    if (temp != null)
        temp(this, new MyEventArgs(val));
}
4b9b3361

Ответ 1

Это паранойя, связанная с нарезкой. Если другой поток отменил подписку на последний обработчик сразу после того, как вы проверили его для null, он может стать null, и вы вызовете исключение. Поскольку делегаты являются неизменными, захват моментального снимка делегата в переменную останавливает это от происходящего.

Конечно, у него есть другой побочный эффект, который вы могли бы (вместо этого) в конечном итоге повысить событие против объекта, который считает, что он уже отписался...

Но подчеркнуть - это только проблема, когда несколько потоков подписываются/отписываются на объект, что является редкостью, а b: не совсем желательно.

Ответ 2

(Из того, что я читал в Essential С# 4.0)

В принципе, из этого кода С#:

public class CustomEventArgs: EventArgs {…}
public delegate void CustomEventHandler(object sender, CustomEventArgs a);
public event CustomEventHandler RaiseCustomEvent;

компилятор будет генерировать код CIL (свободно), эквивалентный следующему С# -коду:

public delegate void CustomEventHandler(object sender, CustomEventArgs a);

private CustomEventHandler customEventHandler; // <-- generated by the compiler

public void add_CustomEventHandler(CustomEventHandler handler) {
  System.Delegate.Combine(customEventHandler, handler);
}

public void remove_CustomEventHandler(CustomEventHandler handler) {
  System.Delegate.Remove(customEventHandler, handler);
}

public event CustomEventHandler customEventHandler {
  add { add_customEventHandler(value) }
  remove { remove_customEventHandler(value) }
}

При копировании события вы фактически скопируете private CustomEventHandler customEventHandler. Поскольку делегат является неизменным, копия не будет затронута при изменении оригинала customEventHandler. Вы можете попробовать этот код, чтобы понять, что я имею в виду:

string s1 = "old"; 
string s2 = s1; 
s1 = "new"; // s2 is still "old"

Еще одна важная характеристика, связанная с созданным CIL код состоит в том, что эквивалент CIL ключевого слова event остается в CIL. Другими словами, событие - это то, что распознает код CIL явно; это не просто конструкция С#. Сохраняя эквивалент event ключевое слово в коде CIL, все языки и редакторы могут предоставить специальные функции, поскольку они могут распознавать событие как особый член класса.

Я думаю, вы были смущены главным образом потому, что вы считали, что событие является синтаксисом сахара для класса, верно?