"Вычитание делегатов имеет непредсказуемый результат" в ReSharper/С#?

При использовании myDelegate -= eventHandler проблем с ReSharper (версия 6):

Вычитание делегатов имеет непредсказуемый результат

Рациональное значение объяснено здесь JetBrains. Объяснение имеет смысл, и, прочитав его, я сомневаюсь во всех моих применениях - для делегатов.

Как тогда,

  • Могу ли я написать событие без авто, не делая ReSharper сварливым?
  • или, есть ли лучший и/или "правильный" способ реализовать это?
  • или, могу ли я просто игнорировать ReSharper?

Вот упрощенный код:

public delegate void MyHandler (object sender);

MyHandler _myEvent;

public event MyHandler MyEvent
{
    add
    {
        _myEvent += value;
        DoSomethingElse();
    }
    remove
    {
        _myEvent -= value; // <-- ReSharper warning here
    }
}

Ответ 1

Не бойся! Первая часть предупреждения ReSharper применяется только к удалению списков делегатов. В вашем коде вы всегда удаляете один делегат. Во второй части речь идет о заказе делегатов после удаления дубликата делегата. Событие не гарантирует порядок исполнения для своих подписчиков, поэтому оно также не влияет на вас.

Поскольку вышеупомянутая механика может привести к непредсказуемым результатам, ReSharper выдает предупреждение всякий раз, когда сталкивается с оператором вычитания делегата.

ReSharper выдает это предупреждение, потому что вычитание делегатов многоадресной рассылки может иметь gotchas, но не полностью осуждает эту функцию языка. К счастью, эти gotchas находятся в крайних случаях, и вы вряд ли столкнетесь с ними, если просто используете простые события. Нет лучшего способа реализовать собственные обработчики add/remove, вы просто должны обратить внимание.

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

Ответ 2

Вы не должны напрямую использовать делегатов для суммирования или вычитания. Вместо этого ваше поле

MyHandler _myEvent;

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

event MyHandler _myEvent;

Использование суммы делегирования или вычитания является опасным, поскольку вы можете потерять события, просто присваивая делегат (согласно объявлению разработчик не будет напрямую вызывать это многоадресный делегат, как когда он объявлен как событие). Чтобы продемонстрировать, если свойство, упомянутое в этом вопросе, не было помечено как событие, приведенный ниже код будет считать, что два первых назначения будут LOST, потому что кто-то просто назначается делегату (который также действителен!).

myObject.MyEvent += Method1; 
myObject.MyEvent += Method2;
myObject.MyEvent = Method3;

При назначении метода 3 я полностью потерял две первоначальные подписки. Использование событий позволит избежать этой проблемы и одновременно удалить предупреждение ReSharper.

Ответ 3

установите для него value = null вместо использования - =