为什么这个通用类型转换失败?

4

我有以下继承:

internal abstract class TeraRow{}

internal class xRow : TeraRow {} // xRow is a child of TeraRow

public IEnumerable<TeraRow> Compare(MappedTables which, DateTime selectionStart
        , DateTime selectionEnd, string pwd)
{
    IEnumerable<xRow> result=CompareX();
    return  (IEnumerable<TeraRow>)result; //Invalid Cast Exception? 

}

无法将类型为“System.Collections.Generic.List1[xRow]”的对象强制转换为类型“System.Collections.Generic.IEnumerable1[TeraRow]”

为什么需要进行强制转换呢?


这种类型的转换将在C# 4.0中得到支持,该版本将于今年晚些时候发布。解决此问题的功能称为协变泛型参数。 - Steve Guidi
4个回答

17

你需要进行强制类型转换,因为 IEnumerable<T> 对 T 不是协变的。你可以这样做:

return result.Cast<TeraRow>();

向下转型通用类型列表...这是少数几个在没有显式定义组合接口的情况下泛型失效的地方之一。 - Brian Rudolph


2

0
如果你需要将转换后的列表表现得像原始引用一样(在索引处设置一个项目也会在原始集合中设置该项目),你可以创建一个实现IList的包装类。(除非我漏掉了什么),对于一个通用解决方案,由于泛型约束的限制,你将需要两个:
public class UpCastList<FromType, ToType> : IList<ToType>
    where FromType : ToType

public class DownCastList<FromType, ToType : IList<ToType>
    where ToType : FromType

另一种可能性是委托转换。
public class CastList<FromType, ToType> : IList<ToType>
{
    public CastList(IList<FromType> source, Func<FromType, ToType> converter) { ... }
}

编辑:如果你只需要一个IEnumerable<T>,那么你可以使用之前提到的Cast<T>扩展方法。


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