一个同事问我今天怎么一个范围内添加到集合。 他从继承的类Collection<T>
有一个得到,只有已包含一些项目该类型的属性。 他想在另一个集合添加项目到属性集合。 他怎么能在C#3友好的方式做到这一点? (注意有关Get-唯一的财产,防止解决方案,如做联盟和重新分配的约束。)
当然,与物业一个foreach。 添加会工作。 但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);
}
}
}
但我有我重新发明轮子的感觉。 我没有发现任何类似System.Linq
或morelinq 。
糟糕的设计? 只需要调用添加? 缺少明显的?
不,这似乎是完全合理的。 有一个List<T>.
的AddRange() ,基本上不只是这一点,但需要你的收集方法是一个具体List<T>
尝试铸造运行循环之前的扩展方法列出。 这样,你可以采取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);
}
}
}
由于.NET4.5
,如果你想要一个班轮你可以使用System.Collections.Generic
的ForEach。
source.ForEach(o => destination.Add(o));
或者更短的
source.ForEach(destination.Add);
性能方面是相同的每个循环(语法糖)。
也不要试图喜欢它分配
var x = source.ForEach(destination.Add)
事业ForEach
是无效的。
请记住,每个Add
将检查收集的能力和调整有必要(慢)时。 随着AddRange
,集合将被设置的能力,然后添加的项目(快)。 这个扩展的方法将是非常缓慢的,但会奏效。
在C5通用收藏图书馆类都支持AddRange
方法。 C5具有更强大的接口,实际上暴露其所有底层实现的功能,并且接口兼容于System.Collections.Generic
ICollection
和IList
接口,这意味着C5
的集合可以被容易地替换为底层实现。
你可以添加你的IEnumerable范围的名单,然后设置的ICollection =到列表中。
IEnumerable<T> source;
List<item> list = new List<item>();
list.AddRange(source);
ICollection<item> destination = list;
或者,你可以做一个ICollection的延伸是这样的:
public static ICollection<T> AddRange<T>(this ICollection<T> @this, IEnumerable<T> items)
{
foreach(var item in items)
{
@this.Add(item);
}
return @this;
}
使用它会就像使用它在列表上:
collectionA.AddRange(IEnumerable<object> items);