web-dev-qa-db-fra.com

L'utilisation d'Action.Invoke est-elle considérée comme la meilleure pratique?

Si j'ai le code ci-dessous, dois-je simplement appeler l'Action ou dois-je appeler Action.Invoke?

public class ClassA
{
  public event Action<string> OnAdd;

  private void SomethingHappened()
  {
    if (OnAdd != null)
     OnAdd("It Happened"); //Should it be OnAdd.Invoke("It Happened") ???????
  }
}

public class ClassB
{

  public ClassB()
  {
    var myClass = new ClassA();
    myClass.OnAdd += Add;
  }

  private void Add(string Input)
  {
    //do something
  }  
}
29
Jon

Les deux sont équivalents, le compilateur convertit OnAdd("It Happened"); en OnAdd.Invoke("It Happened"); pour vous.

Je suppose que c'est une question de préférence, mais je préfère personnellement la forme terser.

Soit dit en passant, il est généralement préférable de prendre une copie locale d'un délégué de niveau classe avant de l'invoquer pour éviter une condition de concurrence critique par laquelle OnAdd n'est pas nulle au moment où elle est vérifiée, mais au moment où il est invoqué:

private void SomethingHappened()
{
  Action<string> local = OnAdd;
  if (local != null)
  {
    local("It Happened");
  }
}
37
Rich O'Kelly

Les deux constructions sont parfaitement équivalentes.

OnAdd("It Happened");

est juste du sucre syntaxique. Dans les coulisses, le compilateur émet un appel à Action<T>.Invoke Dans le MSIL résultant. Utilisez donc celui qui vous est le plus lisible (pour moi, OnAdd("It Happened"); est suffisamment lisible).

11
Darin Dimitrov

Quelque chose que j'ai remarqué à ce sujet avec la dernière version de C # 6 car cela peut encourager Invoke à être plus utilisé et j'ai pensé l'ajouter à cette ancienne question au cas où cela aiderait quelqu'un:

"Ancienne" façon:

Action<string> doSomething = null; // or not null
if (doSomething != null)
    doSomething("test");

Manière pragmatique possible (similaire au modèle de délégué d'événement vide):

Action<string> doSomethingPragmatic = s => { }; // empty - might be overwritten later
doSomethingPragmatic("test");

C # 6:

Action<string> doSomethingCs6 = null; // or not null
doSomethingCs6?.Invoke("test");

// Not valid C#:
// doSomethingCs6?("test")
// doSomethingCs6?.("test")
10
jamespconnor

Ils sont exactement équivalents, sauf si vous rencontrez un bug très étrange autour des fonctions anonymes .

Personnellement, j'utilise généralement le raccourci, mais il arrive parfois qu'il soit plus lisible d'appeler explicitement Invoke. Par exemple, vous pourriez avoir:

if (callAsync)
{
    var result = foo.BeginInvoke(...);
    // ...
}
else
{
    foo.Invoke(...);
    // ...
}

Ici, l'utilisation explicite de Invoke est utile pour la symétrie.

Voir la section 15.4 de la spécification C # 4 pour plus de détails sur l'appel de délégué, bien qu'il ne le spécifie pas explicitement en termes d'appel de la méthode Invoke.

6
Jon Skeet