20

为什么我不能将 aList<AnonymousObject>转换为 a 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]

为什么我不能将匿名类型的列表强制转换为 a dynamic,或者像错误所说的那样对object类型进行强制转换?我该如何解决这个问题?

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

请帮助,提前谢谢。

4

2 回答 2

49

由于List<T>是不变的,而不是协变的,因此您必须将其转换IEnumerable<dynamic>支持协变的:

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

有关协变的更多信息

于 2013-04-24T03:50:20.710 回答
9

首先,使用泛型进行投射不是那样工作的。此演员表无效:

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

原因是 List 不是协变的。如果是这样,source2.Add(source2);当它应该只有字符串时,你可以突然地 source1 包含自己。

其次,匿名类型只是编译器声明的具有只读属性和值相等语义的类。如果您创建了一个具有只读属性和值相等语义的类,则您的类将与匿名类型相同,除了您的类型将具有开发人员确定的名称,而匿名类型具有编译器确定的名称。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();
于 2013-04-24T03:52:59.303 回答