以下のコードがある場合、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
}
}
2つは同等であり、コンパイラはOnAdd("It Happened");
をOnAdd.Invoke("It Happened");
に変換します。
好みの問題だと思いますが、個人的にはより簡潔な形式を好みます。
余談ですが、一般的には、OnAdd
がチェックされた時点でnullではないが呼び出されます:
private void SomethingHappened()
{
Action<string> local = OnAdd;
if (local != null)
{
local("It Happened");
}
}
2つの構造は完全に同等です。
_OnAdd("It Happened");
_
単なる構文糖です。舞台裏では、コンパイラは結果のMSILで_Action<T>.Invoke
_の呼び出しを発行します。したがって、より読みやすいものを使用してください(私にとってはOnAdd("It Happened");
でも十分に読みやすいです)。
最新の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")
匿名関数に関する非常に奇妙なバグ に遭遇しない限り、それらはまったく同等です。
個人的に私通常はショートカットフォームを使用しますが、たまにInvoke
を明示的に呼び出すと読みやすくなります。たとえば、次のものがあります。
if (callAsync)
{
var result = foo.BeginInvoke(...);
// ...
}
else
{
foo.Invoke(...);
// ...
}
ここで、Invoke
の明示的な使用は対称性に役立ちます。
デリゲート呼び出しの詳細については、C#4仕様のセクション15.4を参照してください。ただし、Invoke
メソッドの呼び出しに関して明示的には指定していません。