1. ホーム
  2. c#

[解決済み] InvokeとDynamicInvokeの違いについて

2022-05-02 03:48:32

質問

デリゲートにおけるInvokeとDynamicInvokeの違いは何ですか?その2つのメソッドの違いを説明するコード例を教えてください。

どのように解決するのですか?

デリゲートインスタンスがあるとき、正確な型を知っているかもしれませんし、あるいは、それが 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 のみがある場合を除き、常に優先されます。 Delegateobject[] .

性能比較のため、デバッガ以外(コンソール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);