将匿名类型的强制列表列表到动态对象列表

Joh*_*ona 16 c# anonymous-types .net-4.0

为什么我不能投List<AnonymousObject>一个List<dynamic>?我有以下代码:

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

然后我使用GridView.DataSource以下代码访问:

var ds = ((List<dynamic>)dgvSomeGridView.DataSource);
....
Run Code Online (Sandbox Code Playgroud)

但它在我投射到List<dynamic>它的线上引发了一个错误,它说:

无法将类型的对象转换System.Collections.Generic.List'1[<>f__AnonymousType0'8[System.Int32,System.String]]为类型System.Collections.Generic.List'1[System.Object].

为什么我不能将匿名类型列表转换为a dynamic,或者将错误描述为object类型?我该如何解决这个问题?

我的代码是在C#,框架4.0,在VS2010 Pro中构建,平台是ASP.NET.

请提前帮助,谢谢.

cuo*_*gle 41

既然List<T>是变体,而不是变体,那么你必须投射IEnumerable<dynamic>哪个支持共变体:

var ds = ((IEnumerable<dynamic>)dgvSomeGridView.DataSource).ToList();
Run Code Online (Sandbox Code Playgroud)

有关协变的更多信息


Amy*_*y B 8

首先,使用泛型进行转换并不是那样的.此演员表无效:

List<string> source = GetStrings();
List<object> source2 = (List<object>) source;
Run Code Online (Sandbox Code Playgroud)

原因是List不是共变体.如果它是,你可以source2.Add(source2);突然source1包含它自己应该只有字符串.

其次,匿名类型只是编译器声明的类,具有readonly属性和值相等语义.如果您创建了一个具有readonly属性和值相等语义的类,则您的类将与匿名类型相同,除非您的类型具有开发人员确定的名称,而匿名类型具有编译器确定的名称.匿名类型并不特别.

第三, 动态变量是一种绕过编译器类型检查的方法.它们不会进行运行时类型检查.您可以使用c#casting语法将类型显式转换为动态...注意:这不是强制转换!您不能对运行时不存在的类型执行运行时强制转换.

但是,包含dynamic类型表达式的操作不会被编译器解析或进行类型检查.编译器将有关操作的信息打包在一起,该信息稍后用于评估运行时的操作.作为过程的一部分,dynamic类型的变量被编译为object类型的变量.因此,类型dynamic仅在编译时存在,而不是在运行时存在.

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
Run Code Online (Sandbox Code Playgroud)

最后,如果你还想要List<dynamic>,请执行以下操作:

var anonList = GetAnonList();
List<dynamic> dynamicList = anonList.Select(x => (dynamic)x).ToList();
Run Code Online (Sandbox Code Playgroud)

但你可以轻松地做到这一点:

var anonList = GetAnonList();
List<object> objectList = anonList.Cast<object>().ToList();
Run Code Online (Sandbox Code Playgroud)