web-dev-qa-db-ja.com

Action.Invokeの使用はベストプラクティスと見なされていますか?

以下のコードがある場合、Actionを呼び出すだけですか、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

2つは同等であり、コンパイラはOnAdd("It Happened");OnAdd.Invoke("It Happened");に変換します。

好みの問題だと思いますが、個人的にはより簡潔な形式を好みます。

余談ですが、一般的には、OnAddがチェックされた時点でnullではないが呼び出されます:

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

2つの構造は完全に同等です。

_OnAdd("It Happened");
_

単なる構文糖です。舞台裏では、コンパイラは結果のMSILで_Action<T>.Invoke_の呼び出しを発行します。したがって、より読みやすいものを使用してください(私にとってはOnAdd("It Happened");でも十分に読みやすいです)。

11
Darin Dimitrov

最新のC#6リリースでこれに気づいたものは、Invokeの使用を促進する可能性があり、誰かを助けるためにこの古い質問に追加すると思いました:

「古い」方法:

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

考えられる実用的な方法(空のイベントデリゲートパターンに似ています):

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

匿名関数に関する非常に奇妙なバグ に遭遇しない限り、それらはまったく同等です。

個人的に私通常はショートカットフォームを使用しますが、たまにInvokeを明示的に呼び出すと読みやすくなります。たとえば、次のものがあります。

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

ここで、Invokeの明示的な使用は対称性に役立ちます。

デリゲート呼び出しの詳細については、C#4仕様のセクション15.4を参照してください。ただし、Invokeメソッドの呼び出しに関して明示的には指定していません。

6
Jon Skeet