デリゲートの Invoke と DynamicInvoke の違いは何ですか? 2 つのメソッドの違いを説明するコード例を教えてください。
ベストアンサー1
デリゲートインスタンスがある場合、正確な型がわかっている場合もあれば、それが であることを知っているだけの場合もあります。正確な型がわかっている場合は、をDelegate
使用できます。Invoke
とても早い- すべてがすでに事前検証済みです。例:
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
ただし、 であることがわかっている場合はDelegate
、パラメータなどを手動で解決する必要があります。これには、アンボックス化などが含まれる可能性があり、多くの反映が行われます。例:
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
args
が含まれていることを明確にするために長文で書いたことに注意してくださいobject[]
。ここでは追加コストが多数あります。
- 配列
- 渡された引数が実際のものに「適合」しているかどうかを検証する
MethodInfo
- 必要に応じて開梱など
- リフレクション呼び出し
- 呼び出し側は戻り値を処理するために何かを行う必要がある
基本的に、DynamicInvoke
できる限り を避けてください。 がInvoke
常に望ましいですが、 と しかない場合は除きDelegate
ますobject[]
。
パフォーマンスを比較するには、デバッガー (コンソール exe) の外部でリリース モードで次のように出力します。
Invoke: 19ms
DynamicInvoke: 3813ms
コード:
Func<int,int> twice = x => x * 2;
const int LOOP = 5000000; // 5M
var watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
twice.Invoke(3);
}
watch.Stop();
Console.WriteLine("Invoke: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
twice.DynamicInvoke(3);
}
watch.Stop();
Console.WriteLine("DynamicInvoke: {0}ms", watch.ElapsedMilliseconds);