【问题标题】:Upcasting Generics向上转换泛型
【发布时间】:2014-04-19 03:39:16
【问题描述】:

好的,我知道这是不可能的,但我想知道是否有人知道解决这个问题的方法。

List<int> numberList = new List<int>();

List<object> objectList = (List<object>)numberList;

这会产生以下错误:

无法将类型“System.Collections.Generic.List{int}”转换为“System.Collections.Generic.List{object}”

这是一个简单的例子,但这是我真正的问题。我有一个动态生成IQueryable{IGrouping{TKey, TElement}} 实例的方法。但是,由于在我的例子中TKey 是动态生成的,所以我只能将IQueryable 返回给调用者。

我希望能够将IQueryable{IGrouping{dynamic, TElement}} 返回给调用者。但是,编译器会抱怨,因为就像在我的第一个示例中一样,它将TKey 转换为对象(对于dynamic),并且不会让我那样转换它。有什么办法解决吗?

更新:

这是我试图解决的一个更接近的例子:

List<int> testList = new List<int>();

var qry = new EnumerableQuery<int>( testList );

var objectQry = (IQueryable<object>)qry;

虽然此示例不会产生编译时错误,但当您尝试运行它时会产生强制转换异常。出于某种原因,即使 IQuerable 是协变的(感谢 Servy 提供的 cmets),一旦我引入了诸如 EnumerableQuery 之类的实现类,它就会失败。

【问题讨论】:

  • 如果不可能,是什么让你认为我们可以做到;)
  • 好吧,作为开发人员和问题解决者,我们通常不接受“否”作为答案。我们正在寻找解决问题的新方法,这就是我的问题。
  • 我知道,很明显你没有看到我微笑中的眨眼。我计划在限制重置后立即投票,我认为这是一个非常有趣的问题!

标签: c# generics casting


【解决方案1】:

试试这个。

List<int> numberList = new List<int>();
List<object> objectList = numberList.Cast<object>().ToList();

Enumerable.Cast&lt;T&gt;

将 IEnumerable 的元素转换为指定类型。

【讨论】:

  • 虽然这个答案适用于我的简单示例,但不适用于我的 IGrouping 案例。尝试执行转换时,LINQ to objects 和 LINQ to Entities 都会产生错误。
【解决方案2】:

您需要为每个新字典构建一个副本,因为字典和列表对于它们的任何通用参数都不是协变的。

(键也通过Keys 属性在输出中提供,以及对本身的序列,因此即使IDictionary&lt;TKey, TValue&gt; 也不能与TKey 协变。)

您可以使用Select 将每个对象映射到一个新对象:

List<Dictionary<int, string>> listOfDicts = new List<Dictionary<int, string>>();
List<Dictionary<object, string>> newList = listOfDicts.Select(dic =>
        dic.ToDictionary(pair => (object)pair.Key, pair => pair.Value))
    .ToList();

IQueryable&lt;T&gt; 另一方面 是协变的,IGrouping 也是如此,因此您可以将这些类型的接口向上转换:

IQueryable<IGrouping<dynamic, int>> query = null;
IQueryable<IGrouping<object, int>> otherQuery = query;

编译和运行都很好。

【讨论】:

  • 感谢您的解释,它就像您编写的那样工作,但经过更多测试,它仍然无法解决我的问题...我将编辑我的示例进行演示。跨度>
  • @NathanA 协方差只能应用于引用类型,不能应用于值类型。 int 是一个值类型。
  • 我想提到 3.5 中不存在协方差会有所帮助,因此我有些困惑。我正在为 3.5 和 4.0 编写一个库,而我正在测试的单元测试正在运行 3.5 构建......很高兴知道。并感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-16
  • 1970-01-01
  • 2011-10-31
  • 1970-01-01
相关资源
最近更新 更多