[英]Convert type of anonymous object in linq or lambda expression
I have the following situation, I have a function which returns a List<object
, because the object can be 2 different types Class1
or Class2
, but never mixed. 我遇到以下情况,我有一个返回
List<object
,因为该对象可以是2个不同的类型Class1
或Class2
,但从不混合。 I use this List for a lot of things, but at some point I need a list with names of the objects: List<string>
. 我将这个List用于很多事情,但是有时需要一个列出对象名称的
List<string>
: List<string>
。
I know how to do this in a for loop, but I would like to know if there is a neat linq/lambda trick for this. 我知道如何在for循环中执行此操作,但是我想知道是否有一个很好的linq / lambda技巧。 Since it simplifies the code.
由于它简化了代码。
// 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();
}
Also I know this can be considered dangerous code, but in my situation the type of the returned object is defined by the useFullProces
boolean and will therefore work. 我也知道这可以视为危险代码,但是在我的情况下,返回对象的类型由
useFullProces
布尔值定义,因此可以正常工作。
I suspect you just want: 我怀疑你只是想要:
List<string> names = useFullProcess
? result.Cast<Class2>().Select(x => x.ID.ToString()).ToList()
: result.Cast<Class1>().Select(x => x.Name).ToList();
You can use a cast within your Select
, but it's not as clear IMO: 您可以在
Select
使用强制类型转换,但IMO尚不明确:
List<string> names = useFullProcess
? result.Select(x => ((Class2) x).ID.ToString()).ToList()
: result.Select(x => ((Class1) x).Name).ToList();
You need to cast the correct object: 您需要投射正确的对象:
resultNames = result.Select(x => ((Class2)x).ID.toString()).ToList();
or: 要么:
resultNames = result.Select(x => (x as Class2).ID.toString()).ToList();
EDIT : As I see there are already two answer which uses cast, so I am going to propose you another solution.That doesn't mean you have to implement it or not. 编辑 :据我所知,已经有两个使用强制转换的答案,所以我将向您提出另一个解决方案。这并不意味着您必须实现它。
If you know you're going to have only Class1
and Class2
as types and each one is available on different if-else branch
you can take advantage of DLR
( dynamic language runtime ). 如果您知道将只有
Class1
和Class2
作为类型,并且每个类型在不同的if-else branch
上都可用, if-else branch
可以利用DLR
(动态语言运行时)。
Let's say you have the 2 classes
you mentioned above. 假设您有上面提到的2个
classes
。
public class Class1
{
public string Name { get; set; }
}
public class Class2
{
public int ID { get; set; }
}
You said you know on each branch what types you. 您说您知道每个分支上的类型。 So on
if
branch let's say you have a list formed by Class2
type objects and on else
branch you have a list with Class1
objects. 因此,在
if
分支上,假设您有一个由Class2
类型的对象形成的列表,在else
分支上,您具有了一个具有Class1
对象的列表。
List<dynamic> result = this.ProcesInput(input, useFullProces);
List<string> resultNames;
At this point you have a list of dynamic objects formed by Class1
or Class2
objects, but never mixed. 此时,您具有由
Class1
或Class2
对象形成的动态对象列表,但从未混合在一起。 So both cast and using dynamic should work. 因此,强制转换和使用动态均应起作用。 You won't get a cast exception because you have objects of same type in your list and also you won't get
RuntimeBindingException
when requesting for a property that doesn't exist on that item from the list, because you know what to ask for ( as you said in your question ). 您不会得到
RuntimeBindingException
异常,因为列表中有相同类型的对象,并且从列表中请求该项目中不存在的属性时,也不会获得RuntimeBindingException
,因为您知道要问什么(正如您在问题中所说的)。
You should be able to do something like this: 您应该能够执行以下操作:
if (useFullProces)
{
resultNames= result.Select(x=>x.ID).ToList();
}
else
{
resultNames = result.Select(x=>x.Name).ToList();
}
Note : If your list is mixed with Class1
and Class2
objects you'll get a runtime exception when requesting for a field that doesn't exists. 注意 :如果您的列表中混有
Class1
和Class2
对象,则在请求不存在的字段时会出现运行时异常。
Not another note : Note I made above is also available for cast. 没有其他注释 :我在上面所做的注释也可用于投射。 You'll get
System.InvalidCastException
exception. 您将获得
System.InvalidCastException
异常。
You won't have intellisense
because your type is evaluated by DLR at execution time and not at the compile time. 您不会有
intellisense
因为您的类型是在执行时而不是在编译时由DLR评估的。 Also you don't need to make other casts, boxing or unboxings in your code. 另外,您无需在代码中进行其他强制转换,装箱或拆箱。
PS: DLR
is available from C# 4.0 PS:C#4.0中提供了
DLR
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.