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

при использовании 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
    }
}

3 ответов


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

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

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

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


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

MyHandler _myEvent;

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

event MyHandler _myEvent;

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

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

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


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