将匿名类型的演员列表转换为动态对象列表

21

为什么我不能将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#语言,.NET Framework 4.0版本,使用VS2010 Pro编译,平台为ASP.NET。

请帮忙解决,谢谢!

2个回答

52

由于List<T>是不变的,不支持协变,因此您需要将其强制转换为支持协变的IEnumerable<dynamic>:

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

了解协变的更多信息


1
请务必在文档头中添加“using System.Linq;”,以防您尚未添加。 - Mario Berthely

9
首先,使用通用类型进行转换并不起作用。这种转换是无效的:
List<string> source = GetStrings();
List<object> source2 = (List<object>) source;

List不是协变的原因。如果它是,你可以使用source2.Add(source2);,然后source1包含它自己,而它应该只有字符串。
其次,匿名类型只是具有只读属性和值相等语义的编译器声明类。如果你创建了一个具有只读属性和值相等语义的类,你的类将与匿名类型相同,只不过你的类型将具有开发人员确定的名称,而匿名类型具有编译器确定的名称。Anon类型并不特别。
第三,dynamic变量是绕过编译器类型检查的一种方式。它们不会绕过运行时类型检查。你可以使用C#转换语法将类型显式转换为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

最后,如果您仍然需要一个List<dynamic>,请执行以下操作:

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

但你同样可以这样做:
var anonList = GetAnonList();
List<object> objectList = anonList.Cast<object>().ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接