繁体   English   中英

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

[英]Convert type of anonymous object in linq or lambda expression

我遇到以下情况,我有一个返回List<object ,因为该对象可以是2个不同的类型Class1Class2 ,但从不混合。 我将这个List用于很多事情,但是有时需要一个列出对象名称的List<string>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();

编辑 :据我所知,已经有两个使用强制转换的答案,所以我将向您提出另一个解决方案。这并不意味着您必须实现它。

如果您知道将只有Class1Class2作为类型,并且每个类型在不同的if-else branch上都可用, 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异常,因为列表中有相同类型的对象,并且从列表中请求该项目中不存在的属性时,也不会获得RuntimeBindingException ,因为您知道要问什么(正如您在问题中所说的)。

您应该能够执行以下操作:

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

注意 :如果您的列表中混有Class1Class2对象,则在请求不存在的字段时会出现运行时异常。

没有其他注释 :我在上面所做的注释也可用于投射。 您将获得System.InvalidCastException异常。

您不会有intellisense因为您的类型是在执行时而不是在编译时由DLR评估的。 另外,您无需在代码中进行其他强制转换,装箱或拆箱。

PS:C#4.0中提供了DLR

暂无
暂无

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

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