C# 为什么在泛型参数约束中强制执行某些排序?
例如,在定义泛型类型参数的约束时,我们必须将C# 为什么在泛型参数约束中强制执行某些排序?,c#,generics,constraints,language-design,C#,Generics,Constraints,Language Design,例如,在定义泛型类型参数的约束时,我们必须将class()放在前面,将new()放在后面 为什么这是,为什么我不能把我的约束按任何顺序排列 除了在class/struct之前,在末尾添加new() 例如: protected T Clone<T>() where T : class, ICopyable<T>, new() protectedt Clone(),其中T:class,ICopyable,new() 选择该顺序没有特别的原因。选择的顺序从更一般到更具体,我
class()
放在前面,将new()
放在后面
为什么这是,为什么我不能把我的约束按任何顺序排列
除了在class
/struct
之前,在末尾添加new()
例如:
protected T Clone<T>() where T : class, ICopyable<T>, new()
protectedt Clone(),其中T:class,ICopyable,new()
选择该顺序没有特别的原因。选择的顺序从更一般到更具体,我认为这是一个相当好的属性
至于“为什么需要命令?”这个问题,对于实现和测试团队来说,更容易由语言强加一个清晰、明确的命令。我们可以允许约束以任何顺序出现,但这给我们带来了什么
我研究语言的时间越长,我就越认为每次你给用户一个选择,你就给了他们一个做出错误选择的机会。C#的一个基本设计原则是,当事情看起来不对劲时,我们会告诉你,并强迫你改正——这不是JavaScript的基本设计原则。它的基本设计原则是“蒙混过关,尽力做到用户的意思”。通过对C#中的正确语法设置更多限制,我们可以更好地确保在程序中良好地表达预期的语义
例如,如果我现在正在设计一种类似C的语言,那么我就不可能有歧义的语法,比如:
class C : X , Y
或
Y显然是一个接口。是X吗?我们无法从语法上判断X是打算作为接口还是类。只需说,这种模糊性会使检测基类型与接口中的循环等事情变得非常复杂。如果像在VB中那样更加详细,那么对所有相关的人来说都会容易得多 与大多数语法相关的问题一样,基本答案是因为规范这么说。我们从C#5.0规范(第10.1.5节)中获得了以下泛型类型约束语法
类型参数约束:
主要约束条件:
次要限制:
构造函数约束:
Eric Lippert出色地解释了它为何以这种方式设计,因此我不会对此进行阐述。作为背景,语言规范规定约束必须按主约束、次约束、构造函数约束的顺序排列,其中主约束只是类或结构,次要约束是给定的接口或类类型,构造函数约束只是new()。至于为什么他们被归类为这样的,并要求该顺序,我不知道。也许带注释的语言规范会对此有所帮助?很有趣,谢谢。这就是我特别感兴趣的原因。+1感谢您花时间提供一些关于所做决策类型和原因的见解。我总是觉得奇怪的是,C#表达继承和实现接口的方式不同于Java(Java是显式的),而Java在大多数其他方面都对C#产生了很大的影响。更奇怪的是,正如您所说,这会使编译器的工作变得复杂,“实现和测试团队更容易”。。这让我感到惊讶。尽管较小语法的实现可能更容易一些,但现在您有一个完整的额外功能需要实现和测试:“当顺序错误时生成错误”“每次您给用户一个选择,您都会给他们一个做出错误选择的机会。”,这是真的。
... where T : X, Y
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 ( )