Декомпилированная сборка - необычный код
Я декомпилировал сборку, используя ILSpy, и один класс, в частности, привлек мое внимание:
public class CustomTextStream : NetworkStream
{
private EventHandler<CustomEventArgs> someEvent;
public event EventHandler<CustomEventArgs> SomePublicEvent
{
add
{
EventHandler<CustomEventArgs> eventHandler = this.someEvent;
EventHandler<CustomEventArgs> eventHandler2;
do
{
eventHandler2 = eventHandler;
EventHandler<CustomEventArgs> value2 =
(EventHandler<CustomEventArgs>)Delegate.Combine(eventHandler2, value);
eventHandler =
Interlocked.CompareExchange<EventHandler<CustomEventArgs>>(
ref this.someEvent, value2, eventHandler2);
}
while (eventHandler != eventHandler2);
}
remove
{
// similar stuff...
}
}
}
Далее в коде похоже, что закрытый делегат используется для запуска фактического события:
if (something != null && somethingElse != 0)
{
this.someEvent(this, new CustomEventArgs(someArg));
}
Вопрос: может ли кто-нибудь догадаться, в чем может быть идея этих пользовательских средств доступа, если предположить, что некая "магия компиляции / декомпиляции" не состоялась? Я не очень знаком с IL, кстати...
(Примечание: приложение является многопоточным и использует сеть, очевидно.)
1 ответ
Это новый код обработчика событий, сгенерированный компилятором. Он был представлен в C# 4 (версия C# 3 была другой)
Interlocked.CompareExchange сравнивает первый аргумент с третьим и, если они равны, заменяет первый аргумент вторым. Это потокобезопасная операция. Цикл используется для случая, когда после назначения переменной eventHandler2 и перед проверкой другой поток изменяет этот делегат. В этом случае Interlocked.CompareExchange не выполняет обмен, условие цикла не оценивается как истина, и делается следующая попытка.
C# 3 генерирует простой код в обработчиках событий:
add { lock(this) { changed = changed + value; } }
Которые имели более низкую производительность и могли вводить тупики.
Есть большая серия статей на эту тему: