转换 linq 或 lambda 表达式中匿名对象的类型

本文关键字:对象 类型 linq lambda 表达式 转换 | 更新日期: 2023-09-27 18:30:39

我有以下情况,我有一个返回List<object的函数,因为对象可以是 2 种不同类型的Class1Class2,但永远不会混合。我把这个列表用于很多事情,但在某些时候,我需要一个包含对象名称的列表:List<string> .

我知道如何在 for 循环中做到这一点,但我想知道是否有一个简洁的 linq/lambda 技巧。因为它简化了代码。

// An extreme simplified version of my code
List<object> result = this.ProcesInput(input, useFullProces);
List<string> resultNames;
// The following ideas didn't work.
if (useFullProces)
{
    resultNames = result.Select(x as Class2 => x.ID.toString()).ToList();
    resultNames = result.Select(x => (Class2)x.ID.toString()).ToList();
}
else
{
    resultNames = result.Select(x as Class1 => x.name).ToList();
}

我也知道这可以被认为是危险的代码,但在我的情况下,返回对象的类型由useFullProces布尔值定义,因此可以工作。

转换 linq 或 lambda 表达式中匿名对象的类型

我怀疑你只是想要:

List<string> names = useFullProcess
    ? result.Cast<Class2>().Select(x => x.ID.ToString()).ToList()
    : result.Cast<Class1>().Select(x => x.Name).ToList();

您可以在Select中使用演员表,但IMO并不那么清楚:

List<string> names = useFullProcess
    ? result.Select(x => ((Class2) x).ID.ToString()).ToList()
    : result.Select(x => ((Class1) x).Name).ToList();

您需要强制转换正确的对象:

resultNames = result.Select(x => ((Class2)x).ID.toString()).ToList();

或:

resultNames = result.Select(x => (x as Class2).ID.toString()).ToList();

编辑:正如我所看到的,已经有两个答案使用cast,所以我将向你提出另一种解决方案。这并不意味着您必须实施或不实施它。

如果您知道您将只有Class1Class2作为类型,并且每个类型都可用于不同的if-else branch则可以利用DLR(动态语言运行时)。

假设您有上面提到的 2 classes

public class Class1
{
   public string Name { get; set; }
}
public class Class2
{
   public int ID { get; set; }
}

说你知道每个分支上的你是什么类型。因此,if分支上,假设您有一个由Class2类型对象组成的列表,else分支上,您有一个包含Class1对象的列表。

List<dynamic> result = this.ProcesInput(input, useFullProces);
List<string> resultNames;

此时,您有一个由Class1Class2对象形成的动态对象列表,但从不混合。因此,强制转换和使用动态都应该有效。您不会收到强制转换异常,因为您的列表中有相同类型的对象,而且在请求列表中该项上不存在的属性时也不会RuntimeBindingException,因为您知道要要求什么(正如您在问题中所说)。

你应该能够做这样的事情:

if (useFullProces)
{
    resultNames= result.Select(x=>x.ID).ToList();  
}
else
{
    resultNames = result.Select(x=>x.Name).ToList();
}

注意:如果您的列表混合了Class1Class2对象,则在请求不存在的字段时,您将收到运行时异常。

不是另一个注释:我上面做的注释也可用于演员。你会得到System.InvalidCastException例外。

您不会intellisense因为您的类型由 DLR 在执行时而不是在编译时计算。此外,您不需要在代码中进行其他转换、装箱或取消装箱。

PS:DLR可从C#4.0获得