假设我在 C# 中有两个类派生自同一个基类:
class Base {}
class A: Base {}
class B: Base {}
我正在处理要投影到
Base
类型的不同子类型的对象列表。所以我做了这样的事情:
IEnumerable<Base> foo = myObjects.Select(o => {
if(o.SomeProperty){
return new A();
} else {
return new B();
}
});
但是,这不会编译,编译器会抛出一个错误,指出它无法推断返回类型。
我的问题是:在这种情况下指定返回类型的最优雅的方法是什么?目前我已将 lambda 主体更改为:
if(o.SomeProperty){
return new A() as Base;
} else {
return new B() as Base;
}
这可行,但我想知道是否有更好的方法。
您的解决方案没问题,但可以通过两种方式改进:
? :
) 将 if-else 语句转换为表达式。as
关键字测试表达式是否可以转换为请求的类型,如果可以则进行转换,否则返回null
。这个测试在这里是多余的,因为您事先知道 A
和 B
源自 Base
。使用简单的演员表代替。IEnumerable<Base> foo = myObjects.Select(
o => o.SomeProperty ? (Base)new A() : (Base)new B());
另一种方法是显式指定
Select
方法的泛型类型参数;但是,它要求您同时指定它们:
IEnumerable<Base> foo = myObjects.Select<SourceDataType, Base>(
o => o.SomeProperty ? new A() : new B());
您的解决方案很好,您还可以在 Select 扩展方法中显式点类型,如下所示:
IEnumerable<Base> foo = myObjects.Select<T, Base>(o => {
if(o.SomeProperty)
{
return new A();
}
else
{
return new B();
}
});
T 是您的 myObjects 集合的一种类型。
自 C# 10 起,有一个附加选项 - 显式指定 lambda 的返回类型,这在某些情况下非常方便:
IEnumerable<Base> foo = myObjects.Select(Base (o) => {
// ...
});