web-dev-qa-db-fra.com

"La soustraction de délégué a un résultat imprévisible" dans ReSharper / C #?

Lors de l'utilisation de myDelegate -= eventHandler Problèmes de ReSharper (version 6):

La soustraction de délégué a un résultat imprévisible

Le rationnel derrière cela est expliqué par JetBrains ici . L'explication est logique et, après l'avoir lue, je doute de toutes mes utilisations de - sur les délégués.

Comment alors ,

  • puis-je écrire un événement non automatique sans rendre ReSharper grincheux?
  • ou, existe-t-il une meilleure façon et/ou "correcte" de mettre cela en œuvre?
  • ou, puis-je simplement ignorer ReSharper?

Voici le code simplifié:

public delegate void MyHandler (object sender);

MyHandler _myEvent;

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

N'ayez pas peur! La première partie de l'avertissement de ReSharper s'applique uniquement à la suppression des listes de délégués. Dans votre code, vous supprimez toujours un seul délégué. La deuxième partie traite de l'ordre des délégués après la suppression d'un délégué en double. Un événement ne garantit pas un ordre d'exécution pour ses abonnés, il ne vous affecte donc pas vraiment non plus.

Étant donné que les mécanismes ci-dessus peuvent conduire à des résultats imprévisibles, ReSharper émet un avertissement chaque fois qu'il rencontre un opérateur de soustraction délégué.

ReSharper émet cet avertissement car la soustraction de délégué de multidiffusion peut avoir des accrochages, il ne condamne pas entièrement cette fonctionnalité de langue. Heureusement, ces pièges sont dans des cas marginaux et il est peu probable que vous les rencontriez si vous instrumentez simplement des événements simples. Il n'y a pas de meilleur moyen d'implémenter vos propres gestionnaires add/remove, vous devez juste en prendre note.

Je suggère de rétrograder le niveau d'avertissement de ReSharper pour ce message à "Astuce" afin que vous ne soyez pas désensibilisé à leurs avertissements, qui sont généralement utiles.

127
Allon Guralnek

Vous ne devez pas utiliser directement les délégués pour additionner ou soustraire. Au lieu de cela, votre domaine

MyHandler _myEvent;

Devrait également être déclaré comme un événement. Cela résoudra le problème sans risquer votre solution et bénéficiera toujours de l'utilisation des événements.

event MyHandler _myEvent;

L'utilisation de la somme ou de la soustraction de délégué est dangereuse car vous pouvez perdre des événements en affectant simplement le délégué (selon la déclaration, le développeur ne déduira pas directement qu'il s'agit d'un délégué de multidiffusion comme lorsqu'il est déclaré en tant qu'événement). À titre d'exemple, si la propriété mentionnée sur cette question n'a pas été signalée comme un événement, le code ci-dessous mettra les deux premières affectations en PERTE, car quelqu'un a simplement été attribué au délégué (ce qui est également valide!).

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

Lors de l'attribution de Method3, j'ai complètement perdu les deux abonnements initiaux. L'utilisation de l'événement évitera ce problème et supprimera en même temps l'avertissement ReSharper.

17
blimac