转换 linq 或 lambda 表达式中匿名对象的类型
本文关键字:对象 类型 linq lambda 表达式 转换 | 更新日期: 2023-09-27 18:30:39
我有以下情况,我有一个返回List<object
的函数,因为对象可以是 2 种不同类型的Class1
或Class2
,但永远不会混合。我把这个列表用于很多事情,但在某些时候,我需要一个包含对象名称的列表: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
布尔值定义,因此可以工作。
我怀疑你只是想要:
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,所以我将向你提出另一种解决方案。这并不意味着您必须实施或不实施它。
如果您知道您将只有Class1
和Class2
作为类型,并且每个类型都可用于不同的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;
此时,您有一个由Class1
或Class2
对象形成的动态对象列表,但从不混合。因此,强制转换和使用动态都应该有效。您不会收到强制转换异常,因为您的列表中有相同类型的对象,而且在请求列表中该项上不存在的属性时也不会RuntimeBindingException
,因为您知道要要求什么(正如您在问题中所说)。
你应该能够做这样的事情:
if (useFullProces)
{
resultNames= result.Select(x=>x.ID).ToList();
}
else
{
resultNames = result.Select(x=>x.Name).ToList();
}
注意:如果您的列表混合了Class1
和Class2
对象,则在请求不存在的字段时,您将收到运行时异常。
不是另一个注释:我上面做的注释也可用于演员。你会得到System.InvalidCastException
例外。
您不会intellisense
因为您的类型由 DLR 在执行时而不是在编译时计算。此外,您不需要在代码中进行其他转换、装箱或取消装箱。
PS:DLR
可从C#4.0获得