web-dev-qa-db-ja.com

C#で動的を使用しない場合

次のようなクラスを作成しています。

public class KeyValue
{
    public readonly string key;
    public readonly object value;
}

この設計の結果として、値は任意のオブジェクトタイプにすることができます。

別の方法として、値に動的を使用することもできます。これは、型キャストを行わないことを意味し、また、私の知る限り、ボックス化/ボックス化解除することなく値型を使用できるためです。

ダイナミックを使用せず、代わりにオブジェクトを使用する理由はありますか?何も考えられないから。

注:ジェネリックの方がはるかに適していることに気づきましたが、私のニーズには適していません。上記は、この質問のためだけの単純化です。

4
9a3eedi

動的を使用する正当な理由が考えられない場合は、見返りとして、コンパイル時間チェックの可能性がほとんどない、またはほとんどないことになります。

不足しているフィールドにアクセスしたときに潜在的なランタイム例外を処理することが合理的である動的言語ScriptEngineまたはWebフォームのような動的コンテナーと対話する必要がない限り、オブジェクトよりもジェネリックを、動的よりもオブジェクトを優先します。ジェネリックスは最高のパフォーマンスを発揮します。オブジェクトを使用すると、少なくとも同じ種類のオブジェクトをあらゆる種類のオブジェクトを同じコンテナに格納することを意図していることを意味します。

ダイナミックは実際のタイプではなく、「オブジェクト」ではないので、決して使用しないでください「あらゆる種類のオブジェクト」を意味するために、実際に使用されるのは、オブジェクトのコントラクトが(メソッド/プロパティシグネチャ)であるを知っている場合です。これは、タイプセーフでない(または少なくとも動的にバインドされる)アクティビティの同じ便利な構文を維持するためのランタイムディスパッチ手段です。それは言っているようなものです:

「OK、実行中のアクティビティが実行時ディスパッチと実行時エラーの影響を受けることがわかっているので、とにかく構文上の砂糖をくれ」

私がダイナミックだと思うとき、私は通常差し迫った存在があると思います:

  1. 動的にバインドされた型へのメソッド呼び出しディスパッチ(IronPython変数など)
  2. mVCコントローラーのプロパティ構文を使用した動的フォームデータへのアクセス

もう1つの正当な用途は、動的ディスパッチ機能を使用してVisitor Patternを実装することですが、従来の仮想メソッドはおそらく高速です。

class FooVisitor {
     void Accept(Expression node) { ... }
     void Accept(Statement node) { ... }
}

foreach(dynamic node in ASTNodes) {
    visitor.Accept(obj);  // will be dispatched at runtime based on type of each obj
}

次の場合は使用しないでください。

  1. パフォーマンスは最優先事項です。
  2. より堅牢なランタイムには静的型チェックが望ましい
  3. タイプはコンパイル時に導出できます
  4. ジェネリック型が行います

不必要に使用した場合、DynamicはC#を動的スクリプト言語に変更することにより、コードの堅牢性を実際に低下させる可能性があります。

16
codenheim

dynamicは主に、C#が静的に型指定されていないPythonなどの言語と相互運用できるようにするために導入されました。このコンテキスト以外で使用している場合は、おそらく機能を失っています。

あなたが言ったように、あなたが提示する限られたコンテキストでは、ジェネリックスを使用する方がはるかに良いです(KeyValuePairクラスは、ここで作成しようとしているものに非常によく似ています)。

5
Stephen

答えは、動的型がコードを改善し、より良い結果を生み出し、人生を楽にするなら、もちろんそれらを使用するべきです。それが彼らのためです!

ガベージコレクターに負荷をかけることを除けば、かなり効率的なボクシング/アンボクシングを絶対に気にする必要はありません。生成された動的型のコードを確認すると、オーバーヘッドが大幅に高くなりますが、それらについても心配する必要はありません。

このゲームの課題は、あなたや他の人が理解して操作できる正しいコードを作成することです。可能な場合はジェネリックを、うまくいく場合はダイナミックを、必要な場合はrawオブジェクトを使用します。次に、最適化する前にベンチマークを行います。または単に進みます。

3
david.pfx

変数タイプとしてobjectを使用している場合、and本当に必要ですto、andあなたは本当にジェネリックが必要なことをしないことを確認します。シナリオは1つ半ありますあなたがdynamicを使うべきではないところで遭遇したこと:

  1. 古いマシンにデプロイする必要があります。 Dynamicは.NET 4.0でのみ使用できるため、保証がないマシンをサポートする必要がある場合は、objectを使用してください。
  2. 同様に、Xamarin(数か月前の時点で追跡していた時点)では、ダイナミクスに対する安定したサポートがまだありませんでした。これはちょっと#1に該当します。基本的に、ターゲットプラットフォームがそれらをサポートしていない場合は、使用しないでください。

しかしそれは変数です。 dynamicを関数パラメーターとして使用すると、関数が動的にディスパッチされます。これは通常ですが、常にそうであるとは限りません。 objectを使用すると、通常のインスタンスのみのディスパッチが使用されます。それ以外の場合は、同じガイドラインが適用されます。

0
Telastyn