C# 类型参数约束是一个类

C# 类型参数约束是一个类,c#,generics,inheritance,interface,covariance,C#,Generics,Inheritance,Interface,Covariance,我注意到其他开发人员也在使用这种技术,但它总是让我感到困惑。我决定今早进行调查,并在MSDN上发现以下内容(来自): 公共类通用列表,其中T:Employee { ... } 为什么我们要使用这个方法,而不是用类中的Employee替换T的所有实例?在我看来,这似乎是对可维护性的胜利。我可以理解将接口限制为包含来自不同继承层次结构的类的一种方式,但是继承已经以一种更明显的方式解决了上述问题,不是吗 这会被认为是一个错误,还是像这样“修复”代码是一个错误 为什么我们要使用这个方法,而不是用类中的

我注意到其他开发人员也在使用这种技术,但它总是让我感到困惑。我决定今早进行调查,并在MSDN上发现以下内容(来自):

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

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

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

要启用:

class Manager : Employee { ... }

var board = new GenericList<Manager> ();
类经理:员工{…}
var board=新的通用列表();
请注意,在这种情况下,您的名字“GenericList”更像“EmployeeList”

我可以理解,将接口限制为包含来自不同继承层次结构的类的一种方式

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

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


是的,但不一样<代码>线路板添加(低端程序)将在继承允许时失败

因为它可能是从Employee派生出来的

public class EvilEmployee : Employee {
    public Int32 Evilness { get; set; }
}
现在可以做

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

这是可能的,因为我们知道,在编译时,T=EvilEmployee和EvilEmployee有一个邪恶属性。如果我们要将列表强制添加到员工列表中(如果不使用OfType),这是不可能的。

其中特意添加了语句。设想这样一种情况,即存在从Employee类派生的类;如果不定义泛型类,则需要为每个派生类定义一个类


例如,如果EmployeeX继承Employee,并且您希望使用泛型方法定义一个仅接受EmployeeX实例的列表,则无需定义新类。

泛型允许您在不需要强制转换的情况下保持类型安全

如果你有

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

   GenericList<Manager> managers = ....

   managers[0].CalculateManagerBonus();
genericslist管理器=。。。。
经理[0]。CalculateManager奖金();
如果你有

   GenericList<Employee> managers = ....

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

  // this is neccessary if there where no generics.
  ((Manager)managers[0]).CalculateManagerBonus();
genericslist管理器=。。。。
//这是一个编译器错误
经理[0]。CalculateManager奖金();
//如果没有泛型,这是必要的。
((经理)经理[0])。CalculateManager奖金();

经理已经是员工了,这在多态性中已经是可能的。。。我遗漏了什么吗?@Sprague:
board.Add(低级程序员)在此将失败。+1简洁-一种在泛型上强制执行类型层次结构安全性的简单方法,同时保持输入/输出类型(例如添加/获取方法)等于类型
T
;如果来电者是非通用的,则简化来电者的使用。谢谢你的回答,Simon已立即向我说明了这一点对于速度。虽然这对我来说是有意义的,但我认为我仍然见过这种方法在非通用方法更合适的时候使用,这可能会使我的视野模糊到更可接受的用途。@sprague:你能举个例子吗?最好是从库中?@Henk Holterman:可以说,在某些情况下,类型参数是多余的。在这种情况下,我最感兴趣的是类型参数在其约束中具有特定类的有效情况。我不想对这种情况做出判断,直到我理解了这种用法的情况(感谢你和其他人,我现在这样做了。)进一步说明:如果具有类约束泛型类型t的类没有返回任何类型t或涉及t的类型的方法,没有类型t或涉及t的类型的ref/out参数,并且不接受类型T或涉及T的类型的使用者,那么通常可以用约束类型替换所有出现的类型T。类本身不介意用约束类型替换泛型,但是如果它有任何提到的返回类型或参数类型,那么希望将类与派生类型一起使用的代码将出现问题。
   GenericList<Employee> managers = ....

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

  // this is neccessary if there where no generics.
  ((Manager)managers[0]).CalculateManagerBonus();