无法将派生对象列表隐式转换为泛型 IEnumerable<T>,其中 T 是基类型

问题描述 投票:0回答:1

我有一个类似的类型系统

class Base {}
class Derived1 : Base {}
class Derived2 : Base {}

我还有派生类型的集合

class MyClass
{
    List<Derived1> Derived1Collection { get; set; }
    List<Derived2> Derived2Collection { get; set; }
}

我想要一个通用方法,可以从这些集合中返回任何内容,例如

GetData<Derived1>()
。像这样实现它:

class MyClass
{
    public static IEnumerable<T> GetData<T>() where T : Base
        => typeof(T) switch // dummy "typeof(T)"
        {
            _ when typeof(T) == typeof(Derived1) => Derived1Collection,
            _ when typeof(T) == typeof(Derived2) => Derived2Collection,
            _ => throw new NotSupportedException($"{typeof(T)} isn't supported."),
        };
}

对于派生集合的每次返回,它都会写入一个错误,例如“无法将类型

List<Derived1>
隐式转换为
IEnumerable<T>
”。但是在每个派生集合中添加转换后,它就消失了,所以这是有效的:

_ when typeof(T) == typeof(Derived1) => Derived1Collection.Cast<T>(),
_ when typeof(T) == typeof(Derived2) => Derived2Collection.Cast<T>(),

为什么会这样?

c# generics inheritance collections
1个回答
0
投票

为什么会这样?

基本上是因为编译器(至少目前)不会根据

typeof(T) == 
检查来推断类型以进行进一步的类型检查。它可以通过类型测试“相反”工作:

class MyClass1
{
    private List<Derived1> Derived1Collection { get; set; } = new() { new Derived1() };
    List<Derived2> Derived2Collection { get; set; } = new() { new Derived2() };

    public IEnumerable<T> GetData<T>() where T : Base
    {
        if (typeof(T) == typeof(Base))
            throw new Exception(); // otherwise the first if will match
        
        if (Derived1Collection is IEnumerable<T> d1)
            return d1;
        if (Derived2Collection is IEnumerable<T> d2)
            return d2;
        
        throw new Exception();
    }
}

请注意,直接收集演员也适用于您的情况:

public IEnumerable<T> GetData1<T>() where T : Base
    => typeof(T) switch // dummy "typeof(T)"
    {
        _ when typeof(T) == typeof(Derived1) => (IEnumerable<T>)Derived1Collection,
        _ when typeof(T) == typeof(Derived2) => (IEnumerable<T>)Derived2Collection,
        _ => throw new NotSupportedException($"{typeof(T)} isn't supported."),
    };
© www.soinside.com 2019 - 2024. All rights reserved.