关于C#:继承List 来实现集合是个坏主意?

Inheriting List<T> to implement collections a bad idea?

我曾经读过imaar spaanjars关于如何构建三层应用程序的文章。(http://imar.spaanjaars.com/416/building-layered-web-applications-with-microsoft-aspnet-20-part-1)这是我编码的基础。

因此,我像他那样通过继承List来实现收集。所以如果我有一个名为Employee的类,为了实现一个集合,我还将有一个类Employees,如下所示。

1
2
3
4
5
6
7
8
9
10
11
class Employee
{
   int EmpID {get;set;}
   string EmpName {get;set;}  

}

class Employees : List<Employee>
{
   public Employees(){}
}

我从来没有真正质疑过这一点,因为它为我所做的工作。但是现在我开始尝试一些东西,我不确定这是否是正确的方法。

例如,如果我想从员工那里得到一个子集,例如

1
 Employees newEmployees = (Employees) AllEmployees.FindAll(emp => emp.JoiningDate > DateTime.Now);

这将引发System.InvalidcastException。但是,如果我使用下面的内容,就没有问题了。

1
List<Employee> newEmployees = AllEmployees.FindAll(emp => emp.JoiningDate > DateTime.Now);

那么,如何实现员工,使我不必在DAL或BLL中明确使用List?或者我该如何摆脱无效的社会例外?


我不会继承List—它引入了这样的问题,实际上没有帮助(因为没有virtual方法可以覆盖)。我可以使用List或者更抽象的IList,或者引入多态性Collection有虚拟方法。

值得一提的是,对于像FindAll这样的情况,您也可以发现linq选项(如.Where()等)是有用的对应项;最显著的是,它们适用于任何IListIEnumerable类,而不仅仅是List和子类。


通过将List分类,你能得到什么好处?如果它不添加任何内容,那么它就是不必要的代码膨胀。如果您没有显示方法,或者通过一个在这里没有显示的构造函数执行契约,那么这可能是子类化的一个有效原因。

在解决铸造问题上,你不能从List降到Employees,因为List不从Employees继承。如果您需要用您的条件返回一个雇员,那么您最好封装调用并将返回的列表项插入到您自己的Employees对象中。这对我来说似乎是浪费时间,除非,如我上面所说,你有一个很好的理由去划分List类。

就个人而言,我会尽可能地使用IList,除非有理由存在,否则不会创建子类。


一个简单的经验法则是从组合开始(例如,围绕一个通用集合包装员工),而不是继承。从基于继承的设计开始,就是把自己画到一个角落。组成更灵活和可修改。


我个人将列表存储为一个容器对象的成员,并且如果需要,提供get访问器到列表本身。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MyCollection<T>
{
    List<T> _table;
    public List<T> Table
    {
        get
        {
            return _table;
        }
    }
    // ... other access/utility functions common for all tables
    //     (CRUD for example)
}

class Employees : MyCollection<Employee>
{
    // ... yet more methods
}

我必须承认,我这样做是为了给自己提供以下方法:

1
2
3
T FindById(int id);
void Add(T entity);
void Remove(T entity);

在基类和:

1
T[] GetEmployeesBy(your_filter_here);

我(仍然)使用.NET 2.0,所以我没有LINQ——也许这就是它的原因。