C# 将范围添加到集合
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1474863/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AddRange to a Collection
提问by TrueWill
A coworker asked me today how to add a range to a collection. He has a class that inherits from Collection<T>
. There's a get-only property of that type that already contains some items. He wants to add the items in another collection to the property collection. How can he do so in a C#3-friendly fashion? (Note the constraint about the get-only property, which prevents solutions like doing Union and reassigning.)
今天一位同事问我如何将范围添加到集合中。他有一个继承自Collection<T>
. 有一个该类型的 get-only 属性已经包含一些项目。他想将另一个集合中的项目添加到属性集合中。他怎么能以 C#3 友好的方式做到这一点?(请注意关于 get-only 属性的约束,这会阻止诸如执行 Union 和重新分配之类的解决方案。)
Sure, a foreach with Property. Add will work. But a List<T>
-style AddRange would be far more elegant.
当然,一个带有属性的 foreach。添加将起作用。但是一个List<T>
风格的 AddRange 会优雅得多。
It's easy enough to write an extension method:
编写扩展方法很容易:
public static class CollectionHelpers
{
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
But I have the feeling I'm reinventing the wheel. I didn't find anything similar in System.Linq
or morelinq.
但我感觉我正在重新发明轮子。我在System.Linq
or morelinq 中没有找到类似的东西。
Bad design? Just Call Add? Missing the obvious?
设计不好?只是调用添加?缺少明显的?
采纳答案by Reed Copsey
No, this seems perfectly reasonable. There is a List<T>.
AddRange()method that basically does just this, but requires your collection to be a concrete List<T>
.
不,这似乎完全合理。有一个List<T>.
AddRange()方法基本上就是这样做的,但要求您的集合是一个具体的List<T>
.
回答by Marcus Griep
The C5 Generic Collections Libraryclasses all support the AddRange
method. C5 has a much more robust interface that actually exposes all of the features of its underlying implementations and is interface-compatible with the System.Collections.Generic
ICollection
and IList
interfaces, meaning that C5
's collections can be easily substituted as the underlying implementation.
在C5通用收藏图书馆类都支持的AddRange
方法。C5 有一个更健壮的接口,它实际上公开了其底层实现的所有功能,并且与System.Collections.Generic
ICollection
和IList
接口兼容,这意味着C5
的集合可以很容易地替换为底层实现。
回答by jvitor83
Remember that each Add
will check the capacity of the collection and resize it whenever necessary (slower). With AddRange
, the collection will be set the capacity and then added the items (faster). This extension method will be extremely slow, but will work.
请记住,每个人Add
都会检查集合的容量并在必要时调整其大小(较慢)。使用AddRange
,集合将设置容量,然后添加项目(更快)。这种扩展方法会非常慢,但会起作用。
回答by Jonathan Jansen
You could add your IEnumerable range to a list then set the ICollection = to the list.
您可以将 IEnumerable 范围添加到列表中,然后将 ICollection = 设置为列表。
IEnumerable<T> source;
List<item> list = new List<item>();
list.AddRange(source);
ICollection<item> destination = list;
回答by rymdsmurf
Try casting to List in the extension method before running the loop. That way you can take advantage of the performance of List.AddRange.
在运行循环之前尝试在扩展方法中强制转换为 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);
}
}
}
回答by Matas Vaitkevicius
Since .NET4.5
if you want one-liner you can use System.Collections.Generic
ForEach.
因为.NET4.5
如果你想要一个班轮,你可以使用System.Collections.Generic
ForEach。
source.ForEach(o => destination.Add(o));
or even shorter as
甚至更短
source.ForEach(destination.Add);
Performance-wise it's the same as for each loop (syntactic sugar).
在性能方面,它与每个循环(语法糖)相同。
Also don'ttry assigning it like
也不要尝试分配它
var x = source.ForEach(destination.Add)
cause ForEach
is void.
原因ForEach
是无效的。
Edit:Copied from comments, Lipert's opinion on ForEach
编辑:从评论中复制,Lipert 对 ForEach 的看法
回答by Katarina Kelam
Or you can just make an ICollection extension like this:
或者你可以像这样制作一个 ICollection 扩展:
public static ICollection<T> AddRange<T>(this ICollection<T> @this, IEnumerable<T> items)
{
foreach(var item in items)
{
@this.Add(item);
}
return @this;
}
Using it would be just like using it on a list:
使用它就像在列表中使用它一样:
collectionA.AddRange(IEnumerable<object> items);
回答by MovGP0
Here is a bit more advanced/production-ready version:
这是一个更高级/生产就绪的版本:
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;
}
}