web-dev-qa-db-ja.com

C#4.0で動的キーワードを使用する必要があるのはいつですか?

C#4.0で動的キーワードを使用する必要があるのはいつですか?.......その使用法を説明するC#4.0の動的キーワードの良い例...

58
ACP

動的のみを使用する必要があります使用しない場合は苦痛です。 MS Officeライブラリのように。他のすべてのケースでは、コンパイルタイプチェックが有益であるため、これを回避する必要があります。以下は、ダイナミックを使用する良い状況です。

  1. SilverlightからJavaScriptメソッドを呼び出す。
  2. COM相互運用。
  3. 多分カスタムクラスを作成せずにXml、Jsonを読み取る。
37
Amitabh

これはどう?私が探していたもので、なぜ「ダイナミック」なしではそれが難しいのかと思っていました。

interface ISomeData {}
class SomeActualData : ISomeData {}
class SomeOtherData : ISomeData {}

interface ISomeInterface
{
    void DoSomething(ISomeData data);
}

class SomeImplementation : ISomeInterface
{
    public void DoSomething(ISomeData data)
    {
        dynamic specificData = data;
        HandleThis( specificData );
    }
    private void HandleThis(SomeActualData data)
    { /* ... */ }
    private void HandleThis(SomeOtherData data)
    { /* ... */ }

}

具象型を受け取るオーバーロードメソッドがない場合は、ランタイム例外をキャッチし、必要に応じて処理する必要があるだけです。

dynamicを使用しないのと同じです:

    public void DoSomething(ISomeData data)
    {
        if(data is SomeActualData)
          HandleThis( (SomeActualData) data);
        else if(data is SomeOtherData)
          HandleThis( (SomeOtherData) data);
        ...
        else
         throw new SomeRuntimeException();
    }
11
user2415376

here で説明されているように、ダイナミクスは設計が不十分な外部ライブラリを使いやすくすることができます。MicrosoftはMicrosoft.Office.Interop.Excelアセンブリの例を提供しています。また、動的を使用すると、このアセンブリを使用するときに多くの煩わしい明示的なキャストを回避できます。

また、@ user2415376とは対照的に、言語の初日からすでにポリモーフィズムが実装されているため、インターフェースを処理する方法としては絶対にありません!
使用できます

  ISomeData specificData = data;

の代わりに

dynamic specificData = data;

さらに、間違ったタイプのデータオブジェクトを渡さないようにします。

6
Ashkan Sirous

このブログ投稿を確認してください これは、c#の動的キーワードについて説明しています。ここに要点があります:

動的キーワードは確かに強力です。動的言語で使用する場合はかけがえのないものですが、静的に型付けされたオブジェクトが単純に実行しないコードを設計する際のトリッキーな状況にも使用できます。

欠点を考慮してください:

  1. コンパイル時の型チェックはありません。これは、単体テスト(咳)に100%の信頼がない限り、リスクを冒していることを意味します。

  2. 動的キーワードは、ランタイムオーバーヘッドが増えるため、従来の静的型付けコードよりも多くのCPUサイクルを使用します。プロジェクトでパフォーマンスが重要な場合(通常は動的)を使用しないでください。

  3. よくある間違いには、publicメソッドのdynamicキーワードにラップされた匿名型を返すことが含まれます。匿名型はアセンブリに固有であり、(パブリックメソッドを介して)アセンブリ全体でそれらを返すとエラーがスローされますが、簡単なテストではこれをキャッチできますが、特定の場所からのみ使用できるパブリックメソッドがあり、それは単に悪い設計です。

  4. それは滑りやすい斜面であり、経験の浅い開発者が何か新しいものを書こうとして、より多くのクラスを回避するために最善を尽くします(これは必ずしも経験の浅い人に限定されるわけではありません)。動的な分析チェック/コードレビューに追加します。

3
Sumit Maingi

それを定義するコードプロジェクトの投稿からの抜粋をコピーしたいと思います。

動的を使用する理由

静的に型付けされた世界では、動的により、開発者は多くのロープをかけることができます。コンパイル時に型がわかるオブジェクトを処理するときは、動的キーワードを絶対に避けてください。以前、最初の反応は否定的だったと言ったので、何が私の心を変えましたか? Margret Attwoodを引用すると、コンテキストがすべてです。静的にタイピングする場合、動的は意味をなさない。不明なタイプや動的なタイプを扱う場合、Reflectionを介してそれと通信する必要があることがよくあります。リフレクティブコードは読みにくく、上記の動的なタイプのすべての落とし穴があります。このコンテキストでは、ダイナミックは非常に理にかなっています。[詳細]

一方、動的キーワードの特徴には次のものがあります。

  1. 動的に型付けされます-これは、宣言された変数の型が実行時にコンパイラによって決定されることを意味します。
  2. 宣言時に初期化する必要はありません。

例えば。、

dynamic str; 

str=”I am a string”; //Works fine and compiles

str=2; //Works fine and compiles
  1. エラーは実行時にキャッチされます

  2. タイプとそれに関連するメソッドおよびプロパティは実行時にのみ認識できるため、Intellisenseは使用できません。 [ https://www.codeproject.com/Tips/460614/Difference-between-var-and-dynamic-in-Csharp]

ダイナミックを使用できるすべてのケースでダイナミックを使用することは間違いなく悪い考えです。これは、プログラムがコンパイル時チェックの利点を失い、速度が大幅に低下するためです。

0
Happy

dynamicの使用が簡単な解決策である最近のケースを次に示します。

いくつかのコードをVB6からC#に移植しました。この移植されたコードは、COM相互運用機能を介してVB6オブジェクトの他のメソッドを呼び出すために必要でした。

呼び出す必要があるクラスは次のようになります。

_class A
{
    void Foo() {...}
}

class B
{
    void Foo() {...}
}
_

(つまり、これはVB6クラスがCOM相互運用機能を介してC#でどのように見えるか、特に自動生成されたCOM呼び出し可能ラッパーです)。

AとBは互いに独立しているため、相互にキャストすることはできず、共通の基本クラスもありません(COMはAFAIKとVB6が確かにサポートしていないことをサポートしていません。また、共通のインターフェースを実装していませんでした-下記参照)。

移植された元のVB6コードはこれを行いました:

_' Obj must be either an A or a B 
Sub Bar(Obj As Object) 
    Call Obj.Foo()
End Sub
_

VB6では、物事をObjectとして渡すことができ、ランタイムはそれらのオブジェクトにメソッドFoo()があるかどうかを判断します。しかし、C#ではリテラル変換は次のようになります。

_// Obj must be either an A or a B 
void Bar(object Obj) 
{
    Obj.Foo();
}
_

これは機能しません。 objectには「Foo」というメソッドがないため、コンパイルできません。C#が型保証されているため、これは許可されません。

したがって、単純な「修正」は、次のようにdynamicを使用することでした。

_// Obj must be either an A or a B 
void Bar(dynamic Obj) 
{
    Obj.Foo();
}
_

これにより、実行時までタイプセーフが延期されますが、正しく実行されていれば問題なく機能します。

私はこれを新しいコードに推奨するつもりはありませんが、この状況では(ここで他の回答から判断すると珍しいことではないと思います)、それは価値がありました。

考慮される代替案:

  • リフレクションを使用してFoo()を呼び出す。おそらく機能しますが、より多くの労力と読みやすさが低下します。

  • ここではVB6ライブラリの変更はありませんでしたが、VB6とCOMがサポートする共通のインターフェイスに関してAとBを定義するアプローチがあるかもしれません。しかし、動的を使用する方がはるかに簡単でした。


注:これはおそらく一時的な解決策になるでしょう。最終的に、残りのVB6コードが移植された場合、適切なクラス構造を使用でき、静的コンパイル時間チェックによりdynamicの使用が置き換えられます。そのような希望に満ちた将来は、メンテナンスのリスクを伴う可能性のあるこのアプローチをより快適に使用できるようになりました。

0
DaveInCaz