首页 > 解决方案 > 代码分析:CA1002:不要公开通用列表。如何理解这种违规行为

问题描述

我已经阅读了很多关于 Do Not Expose Generic 的帖子,但我仍然没有得到确切的分辨率。我编写了一个示例控制台应用程序,它分别使用 List 和 List 作为返回类型和参数。在运行代码分析时,它会显示Do Not Expose Generic List正如 msdn 所说

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

修复是

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

如果我使用System.Collections.Generic.ICollection<T>. 即使在函数调用者之后,我仍然可以添加项目。那么通用集合有什么用。下面是代码:

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

        }
    }

现在,如果我将返回类型更改为Collection<Person>并将参数更改为Collection<Person> 输出是相同的。当我们公开一个通用列表时,我将返回类型和参数列表更改为ICollection<Person>/ IEnumerable。如果我把ICollection. 在该方法之后,我仍然可以向其中添加项目。修改代码:

public static ICollection<Person> AddPersonsToCurrentList(Collection<Person> personsList )
        {
            personsList.Add(new Person(){ Age = 11, Name = "Vijay" });
            return personsList;
        }

但是我仍然公开了通用集合,用户仍然可以在调用该方法之前或之后添加项目。任何人都可以帮助我与性能和其他各种其他属性List<T>相比如何有用。Collection<T>

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

标签: c#generics

解决方案


您被警告 List 对象不灵活,并且您正在限制外部开发人员使用该具体类型。通常,在开发可供其他开发人员使用的代码时,最佳实践是要求尽可能抽象的实现,只实现方法中需要的功能。

如果需要,这允许最终用户提供他们自己的实现。例如,如果您在方法中所做的只是枚举列表,则List<Person>可以改为依赖于,而不是要求 type 。IEnumerable<Person>

这为您的 API 用户提供了实现自己的 List 类型/帮助程序的灵活性,并且只要他们从 IEnumerable 继承(这是保证您可以通过您的类型枚举的合同),它们仍然可以正常工作。

在您的示例中,您要求 T 类型的 List或从 T 类型的 List 继承的东西,并且被警告List<T>不应将具体类型用于继承。


推荐阅读