web-dev-qa-db-ja.com

ダイナミックラング。ランタイムとリフレクション

新しいプロジェクトで動的キーワードを使用することを計画しています。しかし、ステップインする前に、Reflectionで動的キーワードを使用する際の長所と短所について知りたいと思います。

プロがどこに続いて、私は動的キーワードに関して見つけることができました:

  • 読み取り可能\保守可能なコード。
  • コードの行数が少なくなります。

動的キーワードの使用に関連するネガティブな点は、次のようなものでした。

  • アプリケーションのパフォーマンスに影響します。
  • 動的キーワードは、内部的にはReflectionのラッパーです。
  • 動的型付けは、見つけにくいバグの温床になる可能性があります。
  • 以前の.NETバージョンとの相互運用性に影響します。

私が出くわした賛否両論が賢明であるかどうかについて私を助けてください?

38
AbrahamJP

読み取り可能\保守可能なコード

私の経験では確かに真実です。

コードの行数が少なくなります。

それほど重要ではありませんが、役に立ちます。

アプリケーションのパフォーマンスに影響します。

ごくわずかです。しかし、リフレクションのようにさえ近くはありません。

動的キーワードは、内部的にはReflectionのラッパーです。

完全に真実ではありません。 dynamicキーワードは、ダイナミックライブラリランタイムを活用します。

[編集:以下のコメントによる修正]

動的言語ランタイムはReflectionを使用しているように見えますが、パフォーマンスの向上はキャッシュ技術のみによるものです。

動的型付けは、見つけにくいバグの温床になる可能性があります。

これは本当かもしれません。コードの書き方によって異なります。コードからコンパイラチェックを効果的に削除しています。テストカバレッジが良好であれば、これはおそらく問題ではありません。そうでなければ、私はあなたが問題にぶつかると思う。

以前の.NETバージョンとの相互運用性に影響します

違います。つまり、古いバージョンに対してコードをコンパイルすることはできませんが、それを行う場合は、古いバージョンをベースとして使用し、その逆ではなくアップコンパイルする必要があります。ただし、.NET 2ライブラリを使用する場合は、app.config/web.configに宣言を含める限り、あまり多くの問題が発生することはありません。

見逃している重要な利点の1つは、COM/ATLコンポーネントとの相互運用性の向上です。

25
pdr

私が出くわした賛否両論が賢明であるかどうかについて私を助けてください?

私があなたの賛否両論に関して持っている懸念は、それらのいくつかがリフレクションの使用とダイナミックの使用の違いに対処していないということです。その動的型付けは、実行時がどの動的型付けシステムにも当てはまるまでキャッチされないバグを生み出します。リフレクションコードには、動的型を使用するコードと同じようにバグがある可能性があります。

賛否両論の観点から考えるのではなく、より中立的な観点から考えてください。私が尋ねたい質問は、「Reflectionを使用することと動的型を使用することの違いは何ですか?」です。

まず、Reflectionを使用すると、正確に要求したものが得られます。動的を使用すると、コンパイル時に型情報が与えられた場合にC#コンパイラが実行したであろうことが得られます。それらは潜在的に2つです完全に異なるもの。特定のメソッドに対するMethodInfoがあり、そのメソッドを特定の引数で呼び出す場合、呼び出されるメソッド、期間。 「動的」を使用する場合は、実行時にDLRに、呼び出すのに適切なメソッドがC#コンパイラの意見であるかどうかを確認するように求めています。 C#コンパイラは、実際に必要な方法とは異なる方法を選択する場合があります。

2番目:Reflectionを使用すると、(コードに適切に高レベルの信頼が付与されている場合)プライベートリフレクションを実行できます。プライベートメソッドを呼び出したり、プライベートフィールドを読み取ったりすることができます。そうするのが良い考えかどうかはわかりません。それは確かに私には危険で愚かなように思えますが、あなたのアプリケーションが何であるかはわかりません。動的を使用すると、C#コンパイラから取得する動作を取得できます。プライベートメソッドとフィールドは表示されません。

3番目:Reflectionを使用すると、作成するコードはメカニズムのようになります。メタデータソースをロードし、いくつかのタイプを抽出し、いくつかのメソッド情報を抽出し、メソッド情報を介してレシーバーオブジェクトのメソッドを呼び出しているようです。方法のすべてのステップは、メカニズムの操作のように見えます。動的では、方法のすべてのステップはビジネスロジックのようになります。他のコードで行うのと同じ方法で、レシーバーでメソッドを呼び出します。重要なことは何ですか?一部のコードでは、メカニズムが実際に最も重要なものです。一部のコードでは、メカニズムが実装するビジネスロジックが最も重要です。適切なレベルの抽象化を強調する手法を選択してください。

4番目:パフォーマンスコストが異なります。 Reflectionを使用すると、キャッシュされた動作は発生しません。つまり、操作は一般に遅くなりますが、キャッシュを維持するためのメモリコストはなく、すべての操作はほぼ同じコストです。 DLRを使用すると、最初の操作は大量の分析を行うため実際には非常に遅くなりますが、分析はキャッシュされて再利用されます。これは、一部のシナリオでの後続の呼び出しの速度の向上と引き換えに、メモリを消費します。アプリケーションの速度とメモリ使用量の適切なバランスは何ですか、私にはわかりません。

100
Eric Lippert

ダイナミックとリフレクションには4つの大きな違いがあります。以下はその詳細な説明です。参照 http://www.codeproject.com/Articles/593881/What-is-the-difference-between-Reflection-and-Dyna

ポイント1. VS呼び出しを検査します

リフレクションは2つのことを実行できます。1つはメタデータを検査できること、もう1つは実行時にメソッドを呼び出す機能もあることです。ダイナミックではメソッドのみを呼び出すことができます。したがって、Visual Studio IDEのようなソフトウェアを作成している場合は、リフレクションが最適です。c#コードから動的に呼び出すだけの場合は、動的が最適なオプションです。

DynamicVsReflection

ポイント2.プライベートとパブリックの呼び出し

動的を使用してプライベートメソッドを呼び出すことはできません。振り返ってみると、プライベートメソッドを呼び出すことが可能です。

ポイント3.キャッシング

Dynamicは内部でリフレクションを使用し、キャッシュの利点も追加します。したがって、オブジェクトを動的に呼び出すだけの場合は、パフォーマンス上の利点が得られるため、動的が最適です。

ポイント4.静的クラス

動的はインスタンス固有です。静的メンバーにアクセスすることはできません。これらのシナリオでは、Reflectionを使用する必要があります。

13

ほとんどの場合、dynamicキーワードを使用しても、意味のある短いコードにはなりません。場合によってはそうなります。それはプロバイダーに依存するので、それ自体が重要な違いです。プレーンCLRオブジェクトにアクセスするためにdynamicキーワードを使用することはおそらく絶対にしないでください。そこにあるメリットは小さすぎます。

Dynamicキーワードは、自動リファクタリングツールを弱体化させ、高カバレッジの単体テストをより重要にします。結局のところ、コンパイラは、使用時に何もチェックしていません。非常に安定した、または本質的に動的に型指定されたAPIと相互運用している場合、これはそれほど問題にはなりませんが、キーワードdynamicを使用して、将来APIが変更される可能性のあるライブラリ(自分で作成したコードなど)にアクセスする場合は特に厄介です。 )。

意味のあるキーワードは慎重に使用し、そのようなコードに十分な単体テストがあることを確認してください。不要な場所や型推論(varなど)で同じことができる場所では使用しないでください。

編集:プラグインに対してこれを行っていることを以下に述べます。 Managed Extensibility Framework はこれを念頭に置いて設計されました-キーワードdynamicとリフレクションよりも良いオプションかもしれません。

4
Eamon Nerbonne

特にリフレクションを行うためにダイナミックを使用している場合、唯一の懸念は以前のバージョンとの互換性です。それ以外の場合は、読みやすく短いため、リフレクションよりも優先されます。とにかくリフレクションを使用すると、強いタイピングと(一部の)パフォーマンスが失われます。

2
Stilgar

Reflectionを使用する場合、古い.NETバージョンとの相互運用性を除いて、動的を使用するためのすべての短所もあります。

アプリケーションのパフォーマンスに影響します

パフォーマンスに影響しますが、Reflectionの使用にも影響します。私が覚えていることから、DLRは、特定のタイプの動的オブジェクトのメソッド/プロパティに初めてアクセスするときに多かれ少なかれReflectionを使用し、タイプ/アクセスターゲットのペアをキャッシュして、後のアクセスがキャッシュ内のルックアップにすぎないようにします。その後、リフレクション

動的キーワードは内部的にReflectionのラッパーです

それが真実であったとしても(上記を参照)、それはどのようにマイナスの点になるでしょうか? Reflectionをラップするかどうかは、アプリケーションに重大な影響を与えることはありません。

動的型付けは、見つけにくいバグの温床になる可能性があります

これは事実ですが、慎重に使用する限り、それほど問題にはならないはずです。さらに、基本的にリフレクションの代わりに使用しますか(つまり、リフレクションを介して何かにアクセスする場合は、可能な限り短い期間だけダイナミックを使用します)、リフレクションを使用する場合よりも、このようなバグのリスクが大幅に高くなることはありません。メソッド/プロパティにアクセスします(もちろん、すべてを動的にすると、さらに問題になる可能性があります)。

以前の.NETバージョンとの相互運用性に影響します

そのためには、それがあなたにとってどれほどの懸念であるかを自分で決める必要があります。

1
Grizzly