没有AddRange()
办法IList<T>
。
如何在IList<T>
不遍历项目和使用Add()
方法的情况下将项目列表添加到?
如果您查看List<T> 的 C# 源代码,我认为 List<T>.AddRange() 具有简单循环无法解决的优化。因此,扩展方法应该简单地检查 IList<T> 是否为 List<T>,如果是,则使用其本机 AddRange()。
查看源代码,您会看到 .NET 人员在他们自己的 LINQ 扩展中为 .ToList() 之类的东西做了类似的事情(如果它是一个列表,则强制转换它......否则创建它)。
public static class IListExtension
{
public static void AddRange<T>(this IList<T> list, IEnumerable<T> items)
{
if (list == null) throw new ArgumentNullException(nameof(list));
if (items == null) throw new ArgumentNullException(nameof(items));
if (list is List<T> asList)
{
asList.AddRange(items);
}
else
{
foreach (var item in items)
{
list.Add(item);
}
}
}
}
AddRange
定义在 上List<T>
,而不是接口上。
您可以将变量声明为List<T>
代替IList<T>
或将其强制转换List<T>
为以获得对AddRange
.
((List<myType>)myIList).AddRange(anotherList);
这不是好的做法(请参阅下面的注释),因为 aIList<T>
可能不是a List<T>
,而是实现接口的其他类型并且很可能没有AddRange
方法 - 在这种情况下,您只会发现代码何时抛出运行时异常。
因此,除非您确定类型确实是 a List<T>
,否则您不应该尝试使用AddRange
.
一种方法是使用is或as运算符测试类型(自 C# 7 起)。
if(myIList is List<T>)
{
// can cast and AddRange
}
else
{
// iterate with Add
}
你可以这样做:
IList<string> oIList1 = new List<string>{"1","2","3"};
IList<string> oIList2 = new List<string>{"4","5","6"};
IList<string> oIList3 = oIList1.Concat(oIList2).ToList();
所以,基本上你会使用Concat()
扩展并ToList()
获得与AddRange()
.
你也可以这样写一个扩展方法:
internal static class EnumerableHelpers
{
public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
}
用法:
IList<int> collection = new MyCustomList(); //Or any other IList except for a fixed-size collection like an array
var items = new[] {1, 4, 5, 6, 7};
collection.AddRange(items);
它仍在迭代项目,但您不必每次调用它时都编写迭代或强制转换。
另一个使用 LINQ 的答案,前提是您要添加的内容是 aList<T>
或者您可以调用ToList()
它:
IEnumerable<string> toAdd = new string[] {"a", "b", "c"};
IList<string> target = new List<string>();
toAdd.ToList().ForEach(target.Add);
IList 没有 AddRange() ,但有 Concat() 结合你的收藏