3

我注意到其他开发人员使用这种技术,但它总是让我感到困惑。我决定今天早上进行调查,并在 MSDN 上发现了以下内容(来自http://msdn.microsoft.com/en-us/library/d5x73970(v=vs.100).aspx):

public class GenericList<T> where T : Employee
{
...
}

为什么我们要使用这个方法而不是用 Employee 替换类中的所有 T 实例?对我来说,这似乎是可维护性的胜利。我可以将限制接口理解为包含来自不同继承层次结构的类的一种方法,但是继承已经以更明显的方式解决了上述问题,不是吗?

这可能被认为是一个错误,还是像这样“修复”代码是一个错误?

4

4 回答 4

7

因为它可能是从 Employee 派生的东西。

public class EvilEmployee : Employee {
    public Int32 Evilness { get; set; }
}

现在可以做...

GenericList<EvilEmployee> list = GetEvilEmployees();
var mostEvilEmployee = list.OrderByDescending(e => e.Evilness).First();

这是可能的,因为我们在编译时知道 T = EvilEmployee 并且 EvilEmployee 具有 Evilness 属性。如果我们将列表强制为不可能的 Employee 列表(不使用 OfType)。

于 2012-04-11T08:19:27.947 回答
5

为什么我们要使用这个方法而不是用 Employee 替换类中的所有 T 实例?

启用:

class Manager : Employee { ... }

var board = new GenericList<Manager> ();

请注意,在这种情况下,您的名称“GenericList”会更像“EmployeeList”

我可以理解对接口的限制是一种包含来自不同继承层次结构的类的方法

类继承和接口有很多共同点。

但是继承已经以更明显的方式解决了上述问题,不是吗?

是的,但不一样。board.Add(lowlyProgrammer);在这里会失败,而继承会允许它。

于 2012-04-11T08:17:17.820 回答
0

where 语句是故意添加的。想想有从 Employee 类派生的类的情况;如果不定义泛型类,则需要为每个派生类定义一个类。

例如,如果 EmployeeX 继承 Employee,并且您想定义一个仅接受 EmployeeX 实例的 List,则通过使用通用方法,您不需要定义新类。

于 2012-04-11T08:20:28.273 回答
0

泛型允许您在无需强制转换的情况下实现类型安全。

如果你有

  public class Manager : Employee
  {
     public double CalculateManagerBonus();
  }

你可以做

   GenericList<Manager> managers = ....

   managers[0].CalculateManagerBonus();

如果你有

   GenericList<Employee> managers = ....

   // this is a compiler error
   managers[0].CalculateManagerBonus();

  // this is neccessary if there where no generics.
  ((Manager)managers[0]).CalculateManagerBonus();
于 2012-04-11T08:24:53.870 回答