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

Строить предупреждения для устаревших событий С#

Кто-нибудь знает о трюке или обходном пути, чтобы заставить компилятор Visual Studio С# выдавать предупреждения сборки при использовании устаревшего события?

Если я создаю простую сборку с открытым событием и применяю атрибут Obsolete к событию, когда я ссылаюсь на эту сборку и подписываюсь на событие в другом проекте, компилятор не выдает предупреждение при создании (даже с высокий уровень предупреждения или предупреждения, установленные для ошибок).

Объявление события в проекте 1:

    public class APIClass
    {
        [Obsolete("Obsolete in v2.0")]
        public event EventHandler ObsoleteEvent;
    }

Использование устаревшего события в Project 2 не вызывает предупреждения сборки:

    private void SubscribeToEvent(APIClass apiClass)
    {
        apiClass.ObsoleteEvent += delegate { };
    }

Когда я открываю исходный файл, Visual Studio распознает событие как устаревшее и добавляет предупреждение (или ошибку) в список ошибок: Background source processing recognizes the warning

Однако, как только я построю, предупреждение исчезнет и не появится в выводе сборки: The warning is gone after compiling

Недопустимое предупреждение о компиляторе, похоже, было зарегистрировано как ошибка, но до тех пор, пока оно не будет исправлено, существует ли какой-либо возможный способ заставить предупреждение когда кто-то использует это событие? В противном случае нет способа предупредить внешних потребителей, что им необходимо изменить код вызова.

4b9b3361

Ответ 1

Кажется, это признанная ошибка, но я могу думать о работе, которая, я надеюсь, будет работать для вашей ситуации.

Ключевое слово event - это всего лишь синтаксический ярлык для делегата многоадресной рассылки, который соответствует конкретной сигнатуре, и раскрывает себя аккуратно аналогично свойству. Одно из решений, которое вы можете попробовать, - сделать событие приватным и выставить метод добавления слушателей, который вы, в свою очередь, считаете устаревшим:

public class APIClass
{
    [Obsolete("Obsolete in v2.0")]
    private event EventHandler ObsoleteEvent;

    [Obsolete("Obsolete in v2.0")]
    public void AddListener(EventHandler eh)
    {
        ObsoleteEvent += eh;
    }

}

private static void SubscribeToEvent(APIClass apiClass)
{
    //apiClass.ObsoleteEvent += delegate { };
    apiClass.AddListener(delegate { });
}

Я надеюсь, что эта работа работает для вас! Удачи!

* edit *

Чтобы еще раз пояснить, почему это ошибка, позвольте мне показать вам MSIL, сгенерированный этим кодом. Следуя аналогии ключевого слова события, ведущего себя как ключевое слово property, он испускает метод "add_ObsoleteEvent" и "remove_ObsoleteEvent". Вы не видите их в своем редакторе, но они связаны тем, что код связан вместе.

Это созданный метод добавления. Обратите внимание, что атрибут 'Obsolete' не добавлен в сгенерированный компилятором метод?

.method private hidebysig specialname instance void 
        add_ObsoleteEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
  // Code size       48 (0x30)
  .maxstack  3

/// rest omitted

Это контрастирует метод "AddListener", который мы написали, к которому мы вручную добавили атрибут "Устаревший". Обратите внимание, что компилятор добавил атрибут "Устаревший" к методу?

.method public hidebysig instance void  AddListener(class [mscorlib]System.EventHandler eh) cil     managed
{
  .custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 10 4F 62 73     6F 6C 65 74 65 20 69 6E 20 76   // ...Obsolete in v
                                                                              32 2E 30 00 00 )                                      // 2.0..
  // Code size       10 (0xa)
  .maxstack  8

/// rest omitted.

Чтобы это исключало предупреждение во время компиляции вне редактора, его можно вручную добавить в MSIL. Я не пробовал это, поэтому не могу сказать, будет ли это работать или нет. Но я думал, что сделаю это редактирование, чтобы показать, почему возникает проблема. Надеюсь, это поможет!