デリゲートでの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);
注object[]
が関係していることを明確にするために、args
ロングハンドを作成しました。ここには多くの追加費用があります:
MethodInfo
の「適合」です基本的に、DynamicInvoke
はできる限り避けてください。 Invoke
とobject[]
のみを持っている場合を除き、Delegate
が常に推奨されます。
パフォーマンスを比較するために、デバッガー(コンソール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);