web-dev-qa-db-ja.com

ジェネリックインターフェイスが動的型を実装できないのはなぜですか?

可能であれば:

IList <dynamic> = new List <dynamic>;

または:

class A <T>
{
 A(T){}
}

class B: A <dynamic> {}

。これを行うことができない理由:

class U: IEnumerable <dynamic> {}

7
Ucho

これは許可されていません。ChrisBurrows(dynamicの作成と実装を支援した人) explains:

まあ、一つには、それはあなたがまだ持っていなかったものを実際にあなたに与えるわけではありません。 IEnumerable<object>を実装した場合、最初のものと2番目のものはすでに存在しています。その場合でも、GetEnumeratorを以前と同じように定義でき、CをIEnumerable<dynamic>に変換できます(これも、構造変換のため)。このように考えてください。誰かがあなたのタイプCを直接見たとしても、あなたが実装するインターフェースを「見る」ことは決してないでしょう。キャストしたときだけ「見る」だけで、その時点ではあなたのIEnumerable<dynamic>は何の役にも立ちませんでした。

それはもっともな理由ですが、返事をするかもしれません。とにかくこれをさせてくれませんか?なぜ人為的に見えるこの制限を課すのですか?良い質問。コンパイラーにこれらのものを出力させようとしたときに初めてこれに遭遇し、動的型をマークするために使用する[Dynamic]属性を生成する場所がないことにすぐに気付きました。メタデータチームは、CLI仕様を読むと、インターフェイス実装とカスタム属性のテーブルで許可された可能性があることを示しているように見えたと報告しましたが、いずれにせよ、私たちの知る人はこれを行ったことがなく、努力が費やされたでしょう。私たちは優先事項と限られた時間の予算を持っていますが、これは削減をもたらしませんでした。

10
Mason Wheeler

それについて考える最も簡単な方法-dynamicはタイプではありません

dynamic は、すべてのコンパイル時チェックをオフにし、代わりに実行時にそれらを実装するコンパイラディレクティブです。

動的変数を宣言する場合:

dynamic t = 123;

t = t.Length;    // crashes at runtime

実際には、変数を System.Object として宣言してから、その変数を含む式のコンパイル時チェックをすべてオフにします。

object t = 123;

unchecked_for_errors
{
    t = t.Length;    
}

<dynamic>は実際には型ではないため、型であるかのように使用することはできません。
代わりに<object>を使用してください。

4
user147272