Tru*_*ill 97 c# collections extension-methods c#-3.0
一位同事今天问我如何为一个系列添加一个范围.他有一个继承自的课程Collection<T>
.这种类型的get-only属性已包含一些项目.他想将另一个集合中的项目添加到属性集合中.他怎么能以C#3友好的方式这样做呢?(注意关于get-only属性的约束,这会阻止像执行Union和重新分配这样的解决方案.)
当然,与物业的foreach.添加将工作.但是A List<T>
风格的AddRange会更加优雅.
编写扩展方法很容易:
public static class CollectionHelpers
{
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我感觉我正在重新发明轮子.我没有发现任何类似System.Linq
或morelinq.
糟糕的设计?只需致电添加?缺少明显的?
Ree*_*sey 57
不,这看起来非常合理.有一个List<T>.
AddRange()方法基本上就是这样做,但要求你的集合是具体的List<T>
.
rym*_*urf 34
在运行循环之前尝试在扩展方法中转换为List.这样您就可以利用List.AddRange的性能.
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
List<T> list = destination as List<T>;
if (list != null)
{
list.AddRange(source);
}
else
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*ius 24
因为.NET4.5
如果你想要单行,你可以使用System.Collections.Generic
ForEach.
source.ForEach(o => destination.Add(o));
Run Code Online (Sandbox Code Playgroud)
甚至更短
source.ForEach(destination.Add);
Run Code Online (Sandbox Code Playgroud)
性能方面与每个循环(语法糖)相同.
也不要尝试分配它
var x = source.ForEach(destination.Add)
Run Code Online (Sandbox Code Playgroud)
原因ForEach
是无效的.
jvi*_*r83 19
请记住,每个人Add
都会检查集合的容量,并在必要时调整其大小(较慢).使用AddRange
,集合将设置容量,然后添加项目(更快).这种扩展方法将非常慢,但会起作用.
这是更高级/生产就绪的版本:
public static class CollectionExtensions
{
public static TCol AddRange<TCol, TItem>(this TCol destination, IEnumerable<TItem> source)
where TCol : ICollection<TItem>
{
if(destination == null) throw new ArgumentNullException(nameof(destination));
if(source == null) throw new ArgumentNullException(nameof(source));
// don't cast to IList to prevent recursion
if (destination is List<TItem> list)
{
list.AddRange(source);
return destination;
}
foreach (var item in source)
{
destination.Add(item);
}
return destination;
}
}
Run Code Online (Sandbox Code Playgroud)