プロパティを取得および設定するメソッドがなぜPropertyInfo
こんなに遅いのでしょうか? を使用してデリゲートを構築するとReflection.Emit
、はるかに高速になります。
彼らは何か重要なことを行っているのでしょうか。そのため、かかる時間は正当化されるのでしょうか。つまり、PropertyInfo のおよびを使用するReflection.Emit
代わりに、 を使用してデリゲートを構築することで、何かを見落としているのでしょうか (開発速度は別として)。GetValue
SetValue
追伸:推測だけではなく、証拠も示してください。
ベストアンサー1
の実装RuntimePropertyInfo
(これはランタイム型の の具体的なサブクラスですPropertyInfo
) は、リフレクション ( ) を介してゲッター メソッドとセッター メソッドを呼び出すことによってGetValue
と を実装しますが、生成されたデリゲートはおそらくメソッドを直接呼び出します。したがって、質問は、コンパイルされた呼び出しと比較して がなぜそれほど遅いのか、ということになります。SetValue
MethodInfo.Invoke
RuntimeMethodInfo.Invoke
を逆コンパイルすると (または の参照ソースを確認すると) 、 が多くのタスクを実行するRuntimeMethodInfo.Invoke
ためであることがわかります。Invoke
- 一貫性チェックを実行します (渡されたパラメータの数と型はシグネチャと一致していますか? 渡されたインスタンスは宣言型と一致していますか? メソッドは静的ですが、インスタンスが渡されましたか?)。
- 可視性チェックと(可視性チェックが回避された場合)セキュリティチェックを実行します。
- パラメータ配列をアンラップし、refパラメータを特別な方法で処理して後で書き戻すことができるようにします。
- 必要に応じてパラメータをアンボックスします。
- RuntimeMethodHandleに関連付けられたランタイム型ハンドルとメソッドハンドルに基づいてメソッドポインタを見つけ、メソッドを呼び出す必要があります。
- 必要に応じて戻り値をボックス化し、
- ref/out パラメータをボックス化してパラメータ配列に格納します。
ランタイムは、デリゲートを実行可能なネイティブ コードにコンパイルするときに、同様の一貫性、セキュリティ、および可視性のチェックを実行します。また、ボックス化/アンボックス化などのコードも出力します。ただし、これらの処理は 1 回だけ実行すればよく、その後はコードが安全に実行できることを保証できます。これにより、実際のメソッド呼び出しは非常に簡単な操作になります (パラメーターをロードしてメソッド アドレスにジャンプします)。
対照的に、 への呼び出しRuntimeMethodInfo.Invoke
(およびGetValue
/への呼び出しSetValue
) では、コンテキスト (パラメータ、インスタンス、戻り値の型の使用法) が不明であるため、すべての作業を繰り返す必要があります。これが、非常に遅くなる理由であると考えられます。
見逃している可能性のある点について: 独自のプロパティ呼び出しデリゲートを発行する場合、もちろん、ボックス化/アンボックス化、ref/out パラメーターなどを自分で処理する必要があります。