C# 代码分析:CA1002:不要公开通用列表。如何理解这种违反

C# 代码分析:CA1002:不要公开通用列表。如何理解这种违反,c#,generics,C#,Generics,我读过很多关于“不要公开泛型”的帖子,但仍然没有得到确切的答案。 我编写了一个示例控制台应用程序,分别使用List和List作为返回类型和参数。在运行代码分析时,它说不要公开泛型列表: System.Collections.Generic.List是为性能而不是继承而设计的通用集合System.Collections.Generic.List不包含使更改继承类的行为更容易的虚拟成员。以下泛型集合是为继承而设计的,应该公开,而不是System.collections.generic.List 而f

我读过很多关于“不要公开泛型”的帖子,但仍然没有得到确切的答案。 我编写了一个示例控制台应用程序,分别使用List和List作为返回类型和参数。在运行代码分析时,它说不要公开泛型列表

System.Collections.Generic.List
是为性能而不是继承而设计的通用集合
System.Collections.Generic.List
不包含使更改继承类的行为更容易的虚拟成员。以下泛型集合是为继承而设计的,应该公开,而不是
System.collections.generic.List

而fix是

若要修复违反此规则的情况,请将
System.Collections.Generic.List
类型更改为设计用于继承的通用集合之一

如果我使用
System.Collections.Generic.ICollection
。即使在函数调用之后,我仍然能够添加项。那么泛型集合的用途是什么呢。 代码如下:

public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public static List<Person> AddPersonsToCurrentList(List<Person> personsList )
        {
            personsList.Add(new Person(){ Age = 11, Name = "Vijay" });
            return personsList;
        }
    }
public class Program
    {
        public static void Main(string[] ar)
        {
            var personList = new List<Person>()
                                          {
                                              new Person(){Age =10,Name="Vj"} 
                                          };

            var resultList = Person.AddPersonsToCurrentList(personList);
            Console.WriteLine(personList.GetType());
            personList.Add(new Person(){Age = 11, Name = "Ajay"});
            Console.ReadKey();

        }
    }
但我仍然公开了泛型集合,用户仍然可以在调用方法之前或之后添加项。 在性能和其他各种属性方面,
List
Collection
相比有何用处


这对我有很大帮助。提前感谢

我们警告您,列表对象是不灵活的,您正在限制外部开发人员使用该具体类型。通常,在开发可供其他开发人员使用的代码时,最好的做法是需要尽可能抽象的实现,只实现方法中所需的功能

这允许最终用户在需要时提供自己的实现。 例如,如果您在方法中所做的一切都是在列表中枚举,那么您可以使用
IEnumerable
,而不需要类型
List

这为您的API用户提供了实现自己的列表类型/帮助程序的灵活性,并且只要它们继承自IEnumerable(这是一个保证您可以通过类型枚举的契约),它们仍将正常工作


在您的示例中,您要求提供类型T的列表,或从类型T的列表继承的内容,并且被警告说,
List
的具体类型不应用于继承。

重要问题:您是否将此API提供给其他人,他们在以后更改它时会遇到很大问题?i、 e.客户或第三方使用的库上的公共API?如果没有,那么更改API也不是问题:坦白地说,忽略它——如果以后需要更改类型(这是一个很大的“如果”),只需稍后更改类型即可。许多代码警告都是与上下文相关的,对于大多数场景,这一条并不适用。是的。我正在处理一个可能由外部开发人员处理的代码库。所以这只是一个原型。所以,如果我分别使用List和List作为返回类型(在方法签名处)和参数,那么将调用此方法的其他开发人员可能会将项添加到List中,这仍然是一个安全问题。即使我把它改成了收藏。它仍然是一种通用集合的公开避免此问题的简单方法:始终对公共方法使用派生最少的接口,
IEnumerable
。这是一个公平的警告,对于使用错误列表的客户端程序员,您无法做任何事情。Add()方法特别危险,它可以通过添加一个不稳定的对象(如null)使您自己的代码崩溃。因此,客户端程序员做了一些错误的事情,但是崩溃发生在他没有编写并且看不见的代码中。这是一个很难处理的保证支持电话。这对微软来说尤其重要,这个分析工具最初是为微软内部使用而开发的。集合没有问题,您可以重写InsertItem并生成良好的诊断。
public static ICollection<Person> AddPersonsToCurrentList(Collection<Person> personsList )
        {
            personsList.Add(new Person(){ Age = 11, Name = "Vijay" });
            return personsList;
        }