有没有办法在C#中使用LINQ在同一个IEnumerable中选择两个值?

时间:2015-03-06 21:36:30

标签: c# linq

我有一个包含两个整数的类,例如AB

public class MyClass {
   public int A { get; set; }
   public int B { get; set; }
   ...other stuff...
}

我在代码中有一个MyCollection类型ObservableCollection<MyClass>,并且需要获得所有值的IEnumerable<int> - A&#39; s和B - 一起列在一个列表中。

我已经弄清楚如何使用相当冗长的代码(为了示例目的而将其简化为仅低于一级,但实际上是&#34;来自&#34;调用和从嵌套列表中选择值的3个级别) :

IEnumerable<int> intsA=
    (from x in MyCollection
            select x.A);
IEnumerable<int> intsB =
    (from x in MyCollection
            select x.B);
IEnumerable<int> allInts = intsA.Concat(intsB);

似乎应该有一种方法可以同时将两个变量选择到同一IEnumerable<int>。显然下面不起作用,但我喜欢像

这样的东西
IEnumerable<int> allInts = (from x in MyCollection select x.A, x.B);

这样的事情是否存在比我上面的更优雅?

我找到了如何在匿名类型here中选择多个值,但这并没有使它成为相同的IEnumerable,并且仍然需要更多代码/处理来获取项目。

(顺便说一句,使用.NET 4.5.1,如果这有所不同。)谢谢!

2 个答案:

答案 0 :(得分:13)

您可以使用SelectMany

var result = source.SelectMany(x => new[] { x.A, x.B });

但是因为你为每个对象分配了一个新的数组,我不知道它的性能如何(或者你可能不那么关心它)。

您可以在类型上声明GetIntValues,返回IEnumerable<int>

public class MyClass {
   public int A { get; set; }
   public int B { get; set; }
   ...other stuff...

   public IEnumerable<int> GetIntValues()
   {
       yield return A;
       yield return B;
   }
}

并像这样使用它:

var result = source.SelectMany(x => x.GetIntValues());

但是每个元素还有一个额外的分配。

答案 1 :(得分:6)

确实很容易:

IEnumerable<int> allInts = MyCollection.Select(i => i.A)
                                       .Concat(MyCollection.Select(i => i.B));

它与你所写的相同,但不那么冗长。它使用lambda语法而不是查询理解语法。

如果您想避免额外分配,请使用它。如果您不关心GC压力,Marcin的解决方案甚至更短。此外,它以与其解决方案不同的顺序输出元素。