如何将两个IEnumerable<T>连接成一个新的IEnumerable<T>?

283

我有两个相同的 IEnumerable<T> 实例,我想要一个新的 IEnumerable<T> 实例,它是这两个实例的连接。

在.NET中是否有内置的方法可以完成此操作,还是我必须自己编写代码实现?


9
请收藏 http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b。 - C-Pound Guru
有没有优雅的方式可以将多个元素集合组合在一起?(相关链接:https://dev59.com/Hm855IYBdhLWcg3wKxHc) - nawfal
6个回答

460

是的,LINQ to Objects 支持使用 Enumerable.Concat 实现此功能:

var together = first.Concat(second);

NB: 如果firstsecond为空,您将收到一个ArgumentNullException。为了避免这种情况并将null视为您对空集的处理方式,请使用Null合并运算符,例如:

var together = (first ?? Enumerable.Empty<string>()).Concat(second ?? Enumerable.Empty<string>()); //amending `<string>` to the appropriate type

2
我总是忘记查找扩展方法,谢谢。 - Samuel Rossille
12
不要忘记,你想执行的动作的名称很可能与你所需要的非常接近,甚至完全相同。一定要浏览 IntelliSense,你会学到很多。 - Adam Houldsworth
3
对于执行 second = first.Concat(second) 是否不好?我们会遇到任何并发问题吗? - user2934433
4
没问题,完全可以。 - Jon Skeet
5
请注意,在代码文件的顶部导入using System.Linq命名空间以在IDE智能感知中查看所需的扩展方法。 - RBT

26
Concat 方法将返回一个实现了 IEnumerable<T> 接口的对象,通过返回一个对象(称其为 Cat),它的枚举器将尝试按顺序使用传入的两个可枚举项(称其为 A 和 B)。如果传入的可枚举项代表的序列在 Cat 的生命周期内不会发生更改,并且可以在没有副作用的情况下读取,则可以直接使用 Cat。否则,最好在 Cat 上调用 ToList() 并使用生成的 List<T>(它将表示 A 和 B 内容的快照)。
一些可枚举项在开始枚举时会进行快照,如果在枚举过程中修改了集合,则将从该快照返回数据。如果 B 是这样一个可枚举项,则任何在 Cat 到达 A 的末尾之前发生的对 B 的更改都会显示在 Cat 的枚举中,但在此之后发生的更改则不会。这种语义可能会令人困惑;快照 Cat 可以避免这些问题。

11

我知道这是一个相对较旧的帖子,但如果你想连接多个IEnumerable,我使用以下方法:

var joinedSel = new[] { first, second, third }.Where(x => x != null).SelectMany(x => x);

这将消除任何空的IEnumerable,并允许进行多次串联。


10
你可以使用以下代码来解决问题:-
public void Linq94() 
{ 
    int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; 
    int[] numbersB = { 1, 3, 5, 7, 8 }; 

    var allNumbers = numbersA.Concat(numbersB); 

    Console.WriteLine("All numbers from both arrays:"); 
    foreach (var n in allNumbers) 
    { 
        Console.WriteLine(n); 
    } 
}

1

基于craig1231的答案,我创建了一些扩展方法...

    public static IEnumerable<T> JoinLists<T>(this IEnumerable<T> list1, IEnumerable<T> list2)
    {
        var joined = new[] { list1, list2 }.Where(x => x != null).SelectMany(x => x);
        return joined ?? Enumerable.Empty<T>();
    }
    public static IEnumerable<T> JoinLists<T>(this IEnumerable<T> list1, IEnumerable<T> list2, IEnumerable<T> list3)
    {
        var joined = new[] { list1, list2, list3 }.Where(x => x != null).SelectMany(x => x);
        return joined ?? Enumerable.Empty<T>();
    }
    public static IEnumerable<T> JoinMany<T>(params IEnumerable<T>[] array)
    {
        var final = array.Where(x => x != null).SelectMany(x => x);
        return final ?? Enumerable.Empty<T>();
    }

-3
// The answer that I was looking for when searching
public void Answer()
{
    IEnumerable<YourClass> first = this.GetFirstIEnumerableList();
    // Assign to empty list so we can use later
    IEnumerable<YourClass> second = new List<YourClass>();

    if (IwantToUseSecondList)
    {
        second = this.GetSecondIEnumerableList();  
    }
    IEnumerable<SchemapassgruppData> concatedList = first.Concat(second);
}

2
这似乎只是现有答案的重复。 - Pang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接