我有一个类似的类型系统
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>(),
为什么会这样?
为什么会这样?
基本上是因为编译器(至少目前)不会根据
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."),
};