将列表项添加到集合时,AddRange()不起作用

时间:2019-03-28 04:40:21

标签: c# generics generic-collections

最近我有一项工作要处理FxCop警告之一- 不要公开通用列表 。因此,我尝试将List<T>更改为ICollection<T>。但是稍后,在进行单元测试时,我发现AddRange()不能正常工作。并没有将元素的集合添加到集合对象中。

这是示例代码

gc.ToList().AddRange(sampleList);

我有两个问题要问

  1. 为什么不将项目添加到集合中。 下面是代码:

    public class GenericClass
    {
        public int Id;
        public string Name;
    }  
    
    
    class Program
    {
         static void Main(string[] args)
         {
    
          ICollection<GenericClass> gc = new  List<GenericClass>();
    
        var sampleList = new List<GenericClass>()
                             {
                                 new GenericClass {Id = 1, Name = "ASD"},
                                 new GenericClass {Id = 2, Name = "QWER"},
                                 new GenericClass {Id = 3, Name = "BNMV"},
                             };
    
        Console.WriteLine(gc.GetType()); // gc is of type
    
        gc.ToList().AddRange(sampleList); // sampleList items are not getting added to gc.
        Console.ReadKey();
    }
    

    }

  2. List<T>继承自ICollection<T>,而List<T>具有AddRange()等功能。当我尝试将父级引用(ICollection<T>)转换为子类对象(List<T>)时,为何Intellisense不建议AddRange()。相反,我需要执行.ToList(),然后显示AddRange()Screenshot

我为此进行了大量搜索。但是找不到令我满意的原因。因此,请帮助我理解。这将是很大的帮助。

2 个答案:

答案 0 :(得分:2)

AddRange()方法工作正常。问题是,您没有仔细阅读ToList()扩展方法的文档,因此也没有意识到ToList()方法返回一个全新的对象。 / p>

来自the documentation

  

从IEnumerable 创建列表

由于您调用AddRange()的对象实际上不是原始集合,因此原始集合保持不变。

从某种意义上说,您的问题是List<T>等同于非常常见的问题“为什么string.Replace()不起作用?”

在您提供的示例中,没有比仅不将List<T>首先隐藏更有效的解决方案。由于使用的是通用的ICollection<T>接口,因此可以编写自己的AddRange()作为扩展方法:

public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> range)
{
    foreach (T t in range)
    {
        collection.Add(t);
    }
}

但是,如果目标是能够修改对象并使用List<T>方法,那么我不认为这真的比将类型保留为AddRange()更好。 / p>

ICollection<T>引用返回到其基础List<T>(如另一个答复者建议的那样)是没有意义的,因为这样做首先会否定使用ICollection<T>接口的任何值。

至少在实际需要修改集合的任何情况下,都将引用保留为List<T>。 (仅使用ICollection<T>在其他情况下公开该列表是很好的,甚至可能是有益的,但这是完全不同的讨论。)

只要我在回答,我就会提到我很怀疑您是否正确理解了FxCop警告的意图,因为公开通用列表本身并没有内在的危害。

答案 1 :(得分:1)

ToList()返回一个新实例,这就是为什么您无法在“ gc”中看到AddRange的结果的原因。如果您确实要使用AddRange,则可以执行以下操作。

((List<GenericClass>)gc).AddRange(sampleList);