InvokeとDynamicInvokeの違い 質問する

InvokeとDynamicInvokeの違い 質問する

デリゲートの 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);

おすすめ記事