我有一个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>);
}
有没有人有更好的方法呢?
答案 0 :(得分:8)
简短的回答是“不”。您需要使用新的BaseClass类型创建一个新集合并填充它。
如果你考虑一下,这是有道理的。如果您可以简单地将您的集合“强制转换”为BaseClass,那么您可以将类型为“BaseClass”的东西粘贴到其中,从而将简单的BaseClass对象强制转换为DerivedClass集合。这将破坏创建类型安全集合的目的。
在极端情况下,如果你有两个派生类,Foo和Bar,你可以通过将集合类型转换回BaseClass集合来强制Bar对象进入Foo对象的集合。
答案 1 :(得分:6)
这称为协方差,虽然目前在.net中不支持泛型,但它将在4.0框架中添加(反之亦然,这是反向差异)。
来自PDC 2008的精彩视频是Anders Hejlsberg提供的关于C#期货的会议:
答案 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