如何将IEnumerable <t>添加到现有ICollection <t>

时间:2016-05-03 09:57:15

标签: c# linq generics ienumerable

鉴于现有ICollection<T>个实例(例如dest),从IEnumerable<T>添加项目的最有效和可读方式是什么?

在我的用例中,我有一些实用方法Collect(IEnumerable items),它返回一个带有ICollection元素的新items,所以我按照以下方式执行:< / p>

public static ICollection<T> Collect<T>(IEnumerable<T> items) where T:ICollection<T>
{
    ...
    ICollection<T> dest = Activator.CreateInstance<T>();
    items.Aggregate(dest, (acc, item) => { acc.Add(item); return acc; });
    ...
    return dest;
}

问题:是否有任何“更好”的方式(更多高效可读)?

更新:我认为使用Aggregate()非常流利,而且效率不如调用ToList().ForEach()。但它看起来不太可读。由于没有其他人同意使用Aggregate()我想了解您不使用Aggregate()的原因。

5 个答案:

答案 0 :(得分:14)

只需使用Enumerable.Concat

IEnumerable<YourType> result = dest.Concat(items);

如果您想要List<T>作为结果,请使用ToList

List<YourType> result = dest.Concat(items).ToList();
// perhaps:
dest = result;

如果dest实际上已经是一个列表而你想修改它,请使用AddRange

dest.AddRange(items);

更新

如果您必须向ICollection<T>方法参数添加项目,则可以使用此扩展名:

public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> seq)
{
    List<T> list = collection as List<T>;
    if (list != null)
        list.AddRange(seq);
    else
    {
        foreach (T item in seq)
            collection.Add(item);
    }
}

// ...

public static void Foo<T>(ICollection<T> dest)
{
    IEnumerable<T> items = ... 
    dest.AddRange(items);
}

答案 1 :(得分:10)

就个人而言,我会选择@ ckruczek对foreach循环的评论:

foreach (var item in items)
    dest.Add(item);

简单,干净,几乎每个人都能立即理解它的作用。

如果您坚持某些方法调用隐藏循环,那么有些人会为ForEach定义自定义IEnumerable<T>扩展方法,类似于为List<T>定义的方法。实施是微不足道的:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (action == null) throw new ArgumentNullException(nameof(action));
    foreach (item in source)
        action(item);
}

鉴于此,你可以写

items.ForEach(dest.Add);

我自己并没有看到太多的好处,但也没有任何缺点。

答案 2 :(得分:4)

我们实际上为此编写了一个扩展方法(以及一堆其他ICollection扩展方法):

public static class CollectionExt
{
    public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> source)
    {
        Contract.Requires(collection != null);
        Contract.Requires(source != null);

        foreach (T item in source)
        {
            collection.Add(item);
        }
    }
}

因此,我们可以在AddRange()上使用ICollection()

ICollection<int> test = new List<int>();
test.AddRange(new [] {1, 2, 3});

注意:如果您想使用List<T>.AddRange(),如果基础集合的类型为List<T>,您可以像这样实现扩展方法:

public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> source)
{
    var asList = collection as List<T>;

    if (asList != null)
    {
        asList.AddRange(source);
    }
    else
    {
        foreach (T item in source)
        {
            collection.Add(item);
        }
    }
}

答案 3 :(得分:1)

items.ToList().ForEach(dest.Add);

如果您不想创建新的集合实例,请创建扩展方法。

public static class Extension
{
    public static void AddRange<T>(this ICollection<T> source, IEnumerable<T> items)
    {
        if (items == null)
        {
            return;
        }

        foreach (T item in items)
        {
            source.Add(item);
        }
    }
}

然后您可以像这样编辑代码:

        ICollection<T> dest = ...;
        IEnumerable<T> items = ...;
        dest.AddRange(items);

答案 4 :(得分:1)

效率最高:

foreach(T item in itens) dest.Add(item)

最具可读性(但效率低下,因为它正在创建一次性列表):

items.ToList().ForEach(dest.Add);

可读性较低,但效率不高:

items.Aggregate(dest, (acc, item) => { acc.Add(item); return acc; });