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

Mig*_*boa 13 c# linq generics ienumerable

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

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

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;
}
Run Code Online (Sandbox Code Playgroud)

问题:这样做是否有"更好"的方式(更有效可读)?

更新:我认为使用它Aggregate()是非常流畅的,并不像调用那么低效ToList().ForEach().但它看起来不太可读.由于没有其他人同意使用Aggregate()我想阅读你的理由不用Aggregate()于此目的.

Tim*_*ter 14

只需使用Enumerable.Concat:

IEnumerable<YourType> result = dest.Concat(items);
Run Code Online (Sandbox Code Playgroud)

如果你想要一个List<T>结果使用ToList:

List<YourType> result = dest.Concat(items).ToList();
// perhaps:
dest = result;
Run Code Online (Sandbox Code Playgroud)

如果dest实际上已经是一个列表,并且您想要修改它,请使用AddRange:

dest.AddRange(items);
Run Code Online (Sandbox Code Playgroud)

更新:

如果必须将项添加到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);
    }
}
Run Code Online (Sandbox Code Playgroud)

// ...

public static void Foo<T>(ICollection<T> dest)
{
    IEnumerable<T> items = ... 
    dest.AddRange(items);
}
Run Code Online (Sandbox Code Playgroud)


小智 10

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

foreach (var item in items)
    dest.Add(item);
Run Code Online (Sandbox Code Playgroud)

简单,干净,几乎每个人都立即明白它的作用.

如果你坚持某些方法调用隐藏循环,那么有些人定义了一个自定义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);
}
Run Code Online (Sandbox Code Playgroud)

鉴于此,您将能够写作

items.ForEach(dest.Add);
Run Code Online (Sandbox Code Playgroud)

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

  • Eric Lippert的必要博客文章:"foreach"vs ForEach":https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/ (6认同)
  • 为什么不为`ICollection <T>`而不是`ForEach`添加`AddRange`扩展方法?这样可以使api更清洁,并且还可以减少操作开销. (4认同)