简体   繁体   English

在 linq.Select() 语句中返回不同的子类型

[英]Returning different sub-types in a linq .Select() statement

Let's say I have two classes in C# that derive from the same base class:假设我在 C# 中有两个类派生自同一个基类 class:

class Base {}

class A: Base {}

class B: Base {}

I'm working with a list of objects that I want to project to different sub-types of type Base .我正在处理要投影到Base类型的不同子类型的对象列表。 So I did something like this:所以我做了这样的事情:

IEnumerable<Base> foo = myObjects.Select(o => {
  if(o.SomeProperty){
    return new A();
  } else {
    return new B();
  }
});

however, this does not compile, the compiler throws an error saying it can't infer the return type.但是,这不会编译,编译器会抛出一个错误,指出它无法推断返回类型。

My question is: what is the most elegant way to specify the return type in cases like this?我的问题是:在这种情况下指定返回类型的最优雅的方法是什么? At the moment I've changed the lambda body to this:目前,我已将 lambda 正文更改为:

if(o.SomeProperty){
  return new A() as Base;
} else {
  return new B() as Base;
}

this works, but I'm wondering if there is a better way.这行得通,但我想知道是否有更好的方法。

Your solution is okay but can be improved in two ways:您的解决方案还可以,但可以通过两种方式进行改进:

  1. Use a ternary operator ( ? : ) to turn the if-else statement into an expression.使用三元运算符 ( ? : ) 将 if-else 语句转换为表达式。
  2. The as keyword tests whether an expression can be cast to the requested type and casts it if it can and returns null otherwise. as关键字测试表达式是否可以转换为请求的类型,如果可以则进行转换,否则返回null This test is superfluous here, since you know in advance that A and B derive from Base .这个测试在这里是多余的,因为你事先知道AB派生自Base Use a simple cast instead.请改用简单的强制转换。
IEnumerable<Base> foo = myObjects.Select(
    o => o.SomeProperty ? (Base)new A() : (Base)new B());

An alternative, is to specify the generic type parameters of the Select method explicitly;另一种方法是显式指定Select方法的泛型类型参数; however, it requires you to specify both of them:但是,它要求您同时指定它们:

IEnumerable<Base> foo = myObjects.Select<SourceDataType, Base>(
    o => o.SomeProperty ? new A() : new B());

Your solution is good, you can also explicitly point types in Select extension method like this:您的解决方案很好,您也可以在 Select 扩展方法中显式指向类型,如下所示:

IEnumerable<Base> foo = myObjects.Select<T, Base>(o => {
  if(o.SomeProperty)
  {
    return new A();
  } 
  else 
  {
    return new B();
  }
});

T is a type of your myObjects collection here. T 是您的 myObjects 集合的一种类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM