将泛型集合转换为基类型

时间:2009-02-11 23:09:16

标签: .net generics collections

我有一个IList<DerivedClass>我想要投射到ICollection<BaseClass>但是当我尝试一个明确的演员时,我得到null。是否可以在不创建和填充新集合的情况下执行此操作?

修改 由于我只想从集合中读取,我转而使用通用方法:

public void PopulateList<BaseClass>(ICollection<T> collection)

然后我可以传递IList<DerivedClass>。有没有一种很好的方法来缓存此列表,以便我可以在需要时刷新它。我的第一个倾向是使用:

Object cachedCollection;
Type cachedType;
public void PopulateList<BaseClass>(ICollection<T> collection) {
    cachedCollection = collection;
    cachedType = T;

    // other stuff...
}

private void Refresh() {
    PopulateList<cachedType>(cachedCollection as ICollection<cachedType>);
}

有没有人有更好的方法呢?

6 个答案:

答案 0 :(得分:8)

简短的回答是“不”。您需要使用新的BaseClass类型创建一个新集合并填充它。

如果你考虑一下,这是有道理的。如果您可以简单地将您的集合“强制转换”为BaseClass,那么您可以将类型为“BaseClass”的东西粘贴到其中,从而将简单的BaseClass对象强制转换为DerivedClass集合。这将破坏创建类型安全集合的目的。

在极端情况下,如果你有两个派生类,Foo和Bar,你可以通过将集合类型转换回BaseClass集合来强制Bar对象进入Foo对象的集合。

答案 1 :(得分:6)

这称为协方差,虽然目前在.net中不支持泛型,但它将在4.0框架中添加(反之亦然,这是反向差异)。

来自PDC 2008的精彩视频是Anders Hejlsberg提供的关于C#期货的会议:

http://channel9.msdn.com/pdc2008/TL16/

答案 2 :(得分:4)

我不认为这是可能的,事实上它不应该是:

class BaseClass {}
class DerivedClass : BaseClass {}
class OtherClass : BaseClass {}

void test()
{
  List<DerivedClass> list = new List<DerivedClass>();
  slice(list); //you want to do this
}

void slice(IList<BaseClass> list)
{
  //yikes! adding OtherClass to List<DerivedClass>
  list.Add(new OtherClass());
}

答案 3 :(得分:2)

不支持在派生类和基类的通用容器之间切换。 (它适用于数组)可以编写一个类型转换器来合理地干净地执行切换,而无需在列表之间手动复制元素。

查看此链接以获取问题/限制的说明和解决方案: http://www.25hoursaday.com/weblog/CommentView.aspx?guid=AF7AA888-A227-454C-8687-71FA77186064

在底部是一个很好的通用版本。

答案 4 :(得分:2)

如果选择.NET 3.5,您可以使用Cast<T>中的System.Core.dll扩展名方法获取该集合的只读IEnumerable<T>

using System.Linq;
...
private void Refresh() {
  PopulateList( cachedCollection.Cast<cachedType>( ) );
}

答案 5 :(得分:0)

您可以将每个元素转换为新的迭代器:

setlocal foldmethod=syntax