Вопрос относительно стоимости / ссылочного типа событий - PullRequest
11 голосов
/ 08 апреля 2010

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

Ответы [ 2 ]

12 голосов
/ 08 апреля 2010

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

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

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

2 голосов
/ 04 октября 2010

(из того, что я прочитал в Essential C # 4.0)

В основном, из этого кода C #:

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

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

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 распознает явно; это не просто конструкция C #. Сохраняя эквивалент event ключевое слово в коде CIL, все языки и редакторы могут предоставить особая функциональность, потому что они могут распознать событие как особый ученик.

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

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