web-dev-qa-db-ja.com

匿名型のリストを動的オブジェクトのリストにキャスト

List<AnonymousObject>List<dynamic>にキャストできないのはなぜですか?私はこの次のコードを持っています:

var datasource = someList.Select(o => new { x = o.A, y = o.B });
dgvSomeGridView.DataSource = datasource.ToList();
dgvSomeGridView.DataBind();

次に、次のコードでGridView.DataSourceにアクセスします。

var ds = ((List<dynamic>)dgvSomeGridView.DataSource);
....

しかし、それをList<dynamic>にキャストした行でエラーがスローされます。

タイプSystem.Collections.Generic.List'1[<>f__AnonymousType0'8[System.Int32,System.String]]のオブジェクトをタイプSystem.Collections.Generic.List'1[System.Object]にキャストできません。

匿名型のリストをdynamicにキャストできないのはなぜですか、またはエラーがobject型に示しているようにですか?どうすればこれを解決できますか?

私のコードはC#、フレームワーク4.0、VS2010 Proでビルド、プラットフォームはASP.NETです。

よろしくお願いします。

18

List<T>は共変ではなく不変であるため、共変をサポートするIEnumerable<dynamic>castする必要があります:

var ds = ((IEnumerable<dynamic>)dgvSomeGridView.DataSource).ToList();

詳細 共変に関する情報

42
cuongle

まず、ジェネリックを使用したキャストはそのようには機能しません。このキャストは無効です:

_List<string> source = GetStrings();
List<object> source2 = (List<object>) source;
_

その理由は、リストが共変ではないためです。もしそうなら、あなたはsource2.Add(source2);をすることができ、突然、source1は文字列だけを持つべきであるときにそれ自身を含みます。

第2に、 匿名型 は、読み取り専用のプロパティと値の等価のセマンティクスを持つコンパイラ宣言クラスです。読み取り専用のプロパティと値の等価性のセマンティクスを持つクラスを作成した場合、クラスは匿名型と同じになりますが、型には開発者が決定した名前が付けられ、匿名型にはコンパイラが決定した名前が付けられます。 Anonタイプは特別ではありません。

第三に、 動的 変数は、コンパイラの型チェックを回避する方法です。ランタイム型チェックを回避しません。 c#キャスト構文を使用して、型を明示的に動的に変換できます...注:これはキャストではありません!実行時に存在しない型への実行時キャストは実行できません。

ただし、動的型の式を含む演算は、コンパイラーによって解決または型チェックされません。コンパイラーは操作に関する情報を一緒にパッケージ化し、その情報は後で実行時に操作を評価するために使用されます。プロセスの一部として、動的型の変数はオブジェクト型の変数にコンパイルされます。したがって、動的型は実行時ではなく、コンパイル時にのみ存在します。

_static void convertToDynamic()
{
    dynamic d;
    int i = 20;
    d = (dynamic)i;
    Console.WriteLine(d);

    string s = "Example string.";
    d = (dynamic)s;
    Console.WriteLine(d);

    DateTime dt = DateTime.Today;
    d = (dynamic)dt;
    Console.WriteLine(d);

}
// Results: 
// 20 
// Example string. 
// 2/17/2009 9:12:00 AM
_

最後に、_List<dynamic>_が必要な場合は、次のようにします。

_var anonList = GetAnonList();
List<dynamic> dynamicList = anonList.Select(x => (dynamic)x).ToList();
_

しかし、あなたはこれを同じくらい簡単に行うことができます:

_var anonList = GetAnonList();
List<object> objectList = anonList.Cast<object>().ToList();
_
8
Amy B