C# 附加/连接两个IEnumerable序列

C# 附加/连接两个IEnumerable序列,c#,ienumerable,unions,C#,Ienumerable,Unions,我有两组数据行。它们都是数不清的。我想将这两个列表附加/连接到一个列表中。我相信这是可行的。我不想做for循环,我注意到两个列表上有一个Union方法和Join方法。有什么想法吗?假设您的对象属于同一类型,您可以使用Union或Concat。请注意,与SQLUNION关键字一样,UNION操作将确保消除重复项,而Concat(如UNION ALL)只需将第二个列表添加到第一个列表的末尾 IEnumerable<T> first = ...; IEnumerable<T>

我有两组数据行。它们都是数不清的。我想将这两个列表附加/连接到一个列表中。我相信这是可行的。我不想做for循环,我注意到两个列表上有一个Union方法和Join方法。有什么想法吗?

假设您的对象属于同一类型,您可以使用
Union
Concat
。请注意,与SQL
UNION
关键字一样,
UNION
操作将确保消除重复项,而
Concat
(如
UNION ALL
)只需将第二个列表添加到第一个列表的末尾

IEnumerable<T> first = ...;
IEnumerable<T> second = ...;

IEnumerable<T> combined = first.Concat(second);

其中,
ConvertToT(TOne f)
ConvertToT(TTwo s)
表示一种操作,该操作以某种方式将
TOne
(和
TTwo
)的实例转换为
T
的实例,我刚刚遇到了一种类似的情况,即需要串联多个序列

自然地在Google/StackOverflow上搜索现有的解决方案,但是没有找到任何不评估可枚举项的内容,例如转换为数组,然后使用
array.Copy()
等,因此我编写了一个名为
ConcatMultiple
的扩展和静态实用方法

希望这能帮助任何需要这样做的人

//
///连接多个序列
/// 
///输入序列元素的类型。
///要连接的第一个序列。
///要连接的其他序列。
/// 
公共静态IEnumerable ConcatMultiple(此IEnumerable优先,参数IEnumerable[]源)
{
if(first==null)
抛出新的ArgumentNullException(“第一”);
if(source.Any(x=>(x==null)))
抛出新的ArgumentNullException(“源”);
返回计数器(源);
}
专用静态IEnumerable ConcatIterator(IEnumerable first,params IEnumerable[]源)
{
foreach(第一个变量为var iteratorVariable)
收益率变量;
foreach(源中的变量可枚举)
{
foreach(枚举中的var迭代器变量)
收益率变量;
}
}
/// 
///连接多个序列
/// 
///输入序列元素的类型。
///要连接的序列。
/// 
公共静态IEnumerable ConcatMultiple(params IEnumerable[]源)
{
if(source.Any(x=>(x==null)))
抛出新的ArgumentNullException(“源”);
返回计数器(源);
}
专用静态IEnumerable ConcatIterator(params IEnumerable[]源)
{
foreach(源中的变量可枚举)
{
foreach(枚举中的var迭代器变量)
收益率变量;
}
}
该方法类似于SQL连接,列表根据条件交叉引用,而不是字符串连接或添加到列表中。该方法和该方法一样,可以做您想要做的事情,但两者都是惰性计算,并且要求参数不为null。它们返回ConcatIterator或UnionIterator,以及。急切的评估会导致不同的行为,如果这是您想要的,那么可以使用下面这样的扩展方法

public static IEnumerable<T> myEagerConcat<T>(this IEnumerable<T> first,
                                                   IEnumerable<T> second)
{
    return (first ?? Enumerable.Empty<T>()).Concat(
           (second ?? Enumerable.Empty<T>())).ToList();
}
公共静态IEnumerable myEagerConcat(此IEnumerable优先,
(可数秒)
{
返回(第一个??可枚举的.Empty()).Concat(
(第二个??Enumerable.Empty()).ToList();
}

延迟调用第二个和后续可枚举项

我通常使用Linq
IEnumerable.Concat()
,但今天我需要100%确保第二个枚举在第一个枚举处理完之后才被枚举。(例如,我不想同时运行的两个db查询)。因此,下面的函数实现了延迟枚举的技巧

    IEnumerable<T> DelayedConcat<T>(params Func<IEnumerable<T>>[] enumerableList)
    {
        foreach(var enumerable in enumerableList)
        {
            foreach (var item in enumerable())
            {
                yield return item;
            }
        }
    }

在本例中,GetEnumerable1函数调用将被延迟,直到GetEnumerable1被枚举完毕。

数据行集是否为同一类型?不同的类型?@Obed……它们是相同的type@Adam....I我说得太快了。我已经完成了工会工作,我得到了重复的记录。是否需要初始化某种类型的密钥属性?@MikeTWebb:
Union
有一个重载,允许您指定
IEqualityComparer
@MikeTWebb:如果此答案解决了您的问题,请记住接受它!谢谢与参考实现几乎相同@TJHeuvel不正确。其中一个接收两个枚举,而我的则接收两个
Func
,并确保在第一个枚举耗尽之前不会创建第二个枚举。
public static IEnumerable<T> myEagerConcat<T>(this IEnumerable<T> first,
                                                   IEnumerable<T> second)
{
    return (first ?? Enumerable.Empty<T>()).Concat(
           (second ?? Enumerable.Empty<T>())).ToList();
}
    IEnumerable<T> DelayedConcat<T>(params Func<IEnumerable<T>>[] enumerableList)
    {
        foreach(var enumerable in enumerableList)
        {
            foreach (var item in enumerable())
            {
                yield return item;
            }
        }
    }
    return DelayedConcat(
                () => GetEnumerable1(),
                () => GetEnumerable2(),
 // and so on.. () => GetEnumerable3(),
                );