为什么在泛型参数约束中强制执行某些排序?

时间:2011-12-15 15:18:14

标签: c# generics constraints language-design

在定义泛型类型参数的约束时,我们必须将class()放在前面,将new()放在最后,例如。

为什么会这样,为什么我不能按任何顺序设置约束?

class / struct之外,new()最后是否还有其他限制?


示例:

protected T Clone<T>() where T : class, ICopyable<T>, new()

2 个答案:

答案 0 :(得分:25)

选择该订单没有特别的理由。所选择的顺序从更一般到更具体,我认为这是一个相当不错的属性。

至于“为什么需要订单?”这个问题,实施和测试团队可以更容易地通过语言强加清晰,明确的命令。我们可以允许约束以任何顺序出现,但这会给我们带来什么?

我在语言上工作的时间越长,我就越觉得每次给用户一个选择时,你都给他们一个做出错误选择的机会。 C#的基本设计原则是我们告诉你什么时候出错了并强迫你做对了 - 这不是JavaScript的基本设计原则。它的基本设计原则是“混淆并尝试做用户的意思”。通过对C#中正确的语法进行更多限制,我们可以更好地确保在程序中很好地表达了预期的语义

例如,如果我今天正在设计一种类似C#的语言,那么就不会有像我这样模糊的语法:

class C : X , Y

... where T : X, Y

Y显然是一个界面。是X?我们无法从语法上说出X是打算成为接口还是类。可以说这种模糊性使得检测基类型与接口中的周期等问题变得非常复杂。对于所有相关的事情来说,如果它更加冗长,就像在VB中一样。

答案 1 :(得分:1)

与大多数语法相关的问题一样,基本答案是因为规范说明了这一点。我们从C#5.0规范(第10.1.5节)

获得通用类型约束的以下语法
  

type-parameter-constraints:

primary-constraint 
secondary-constraints
constructor-constraint 
primary-constraint   ,   secondary-constraints
primary-constraint   ,   constructor-constraint 
secondary-constraints ,   constructor-constraint 
primary-constraint   ,  secondary-constraints   ,   constructor-constraint 
     

初级约束:

class-type 
class 
struct 
     

次要约束:

interface-type
type-parameter 
secondary-constraints   ,   interface-type
secondary-constraints   ,   type-parameter
     

构造函数约束:

new (   )

Eric Lippert在解释为什么设计这种方式方面做得非常出色,所以我不会对此进行阐述。