Всегда ли гарантируется, что вспомогательное поле события, сгенерированного компилятором, будет использовать то же имя, что и событие?

C#позволяет нам создавать пользовательские методы доступа к событиям .

Action _custom;
public event Action Custom
{
    add { _custom = (Action)Delegate.Combine( _custom, value ); }
    remove { _custom = (Action)Delegate.Remove( _custom, value ); }
}

Если вы их не укажете, компилятор создаст их для вас . Спецификация языка C#:

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

Декомпилированный исходный код с использованием dotPeek для простого public event Action Public;выглядит следующим образом:

  private Action Public;

  public event Action Public
  {
    add
    {
      Action action = this.Public;
      Action comparand;
      do
      {
        comparand = action;
        action = Interlocked.CompareExchange(
                     ref this.Public, comparand + value, comparand);
      }
      while (action != comparand);
    }
    remove
    {
      Action action = this.Public;
      Action comparand;
      do
      {
        comparand = action;
        action = Interlocked.CompareExchange(
                    ref this.Public, comparand - value, comparand);
      }
      while (action != comparand);
    }
  }

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

public static FieldInfo GetFieldInfo( this EventInfo eventInfo )
{
    Contract.Requires( eventInfo != null );

    return eventInfo.DeclaringType.GetField(
        eventInfo.Name,
        BindingFlags.DeclaredOnly | BindingFlags.Instance |
            BindingFlags.Public | BindingFlags.NonPublic );
}

Это работает, но вызывает вопрос:Всегда ли гарантируется, что вспомогательное поле события, сгенерированного компилятором, будет использовать то же имя, что и событие?

Невозможно создать пользовательские методы доступа к событиям, которые обращаются к делегату с таким же именем с помощью Visual Studio. В результате появляется сообщение:«Участник с таким именем уже объявлен». Мне интересно, можете ли вы сделать вывод, что любое событие, для которого нет вспомогательного делегата с таким же именем, является событием с пользовательскими средствами доступа.

9
задан Community 23 May 2017 в 12:15
поделиться