简体   繁体   English

如何将一系列项目添加到 IList?

[英]How to add a range of items to an IList?

There is no AddRange() method for IList<T> . IList<T>没有AddRange()方法。

How can I add a list of items to an IList<T> without iterating through the items and using the Add() method?如何将项目列表添加到IList<T>而不遍历项目并使用Add()方法?

If you look at the C# source code for List<T> , I think List<T>.AddRange() has optimizations that a simple loop doesn't address.如果您查看List<T>C# 源代码,我认为 List<T>.AddRange() 具有简单循环无法解决的优化。 So, an extension method should simply check to see if the IList<T> is a List<T>, and if so use its native AddRange().因此,扩展方法应该简单地检查 IList<T> 是否是 List<T>,如果是,则使用其原生 AddRange()。

Poking around the source code, you see the .NET folks do similar things in their own LINQ extensions for things like .ToList() (if it is a list, cast it... otherwise create it).仔细研究源代码,您会看到 .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 is defined on List<T> , not the interface. AddRangeList<T>上定义,而不是在接口上定义。

You can declare the variable as List<T> instead of IList<T> or cast it to List<T> in order to gain access to AddRange .您可以将变量声明为List<T>而不是IList<T>或将其AddRangeList<T>以获得对AddRange访问AddRange

((List<myType>)myIList).AddRange(anotherList);

This is not good practice (see comments below), as an IList<T> might not be a List<T> , but some other type that implemented the interface and may very well not have an AddRange method - in such a case, you will only find out when your code throws an exception at runtime.这不是一个好的做法(请参阅下面的评论),因为IList<T>可能不是List<T> ,而是实现了接口的其他一些类型并且很可能没有AddRange方法 - 在这种情况下,您只会发现您的代码在运行时何时抛出异常。

So, unless you know for certain that the type is indeed a List<T> , you shouldn't try to use AddRange .因此,除非您确定该类型确实是List<T> ,否则不应尝试使用AddRange

One way to do so is by testing the type with the is or as operators (since C# 7).一种方法是使用isas运算符测试类型(自 C# 7 起)。

if(myIList is List<T>)
{
   // can cast and AddRange
}
else
{
   // iterate with Add
}

You could do something like this:你可以这样做:

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();

So, basically you would use the Concat() extension and ToList() to get a similar functionality as AddRange() .所以,基本上你会使用Concat()扩展和ToList()来获得与AddRange()类似的功能。

Source 来源

You could also write an extension method like this:您还可以编写这样的扩展方法:

internal static class EnumerableHelpers
{
    public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items)
    {
        foreach (var item in items)
        {
            collection.Add(item);
        }
    }
}

Usage:用法:

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);

Which is still iterating over items, but you don't have to write the iteration or cast every time you call it.它仍在迭代项目,但您不必每次调用它时都编写迭代或强制转换。

Another answer using LINQ, provided the thing you're adding is a List<T> or you are able to call ToList() on it:使用 LINQ 的另一个答案,前提是您添加的是List<T>或者您可以在其上调用ToList()

IEnumerable<string> toAdd = new string[] {"a", "b", "c"};
IList<string> target = new List<string>();

toAdd.ToList().ForEach(target.Add);

IList 没有 AddRange() ,但有结合你的集合的 Concat()

var var1 = output.listDepartment1
var var2 = output.listDepartment2  
var1.AddRange(var2);
var list = var1;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM