C# 为什么必须最后指定new()约束?

C# 为什么必须最后指定new()约束?,c#,.net,generics,constraints,C#,.net,Generics,Constraints,C#编译器要求最后指定new()约束。 根据MSDN: 当与其他设备一起使用时 约束,新的()约束必须 最后指定 为什么会有这样的限制?因为在其他约束(例如类)上可以指定构造函数,而在其他约束(例如接口)上则不能 因此,如果new()先出现,然后是接口上的约束,则会出现错误,因为接口上不能有new()约束。,因为规范这么说。它之所以这么说,可能是因为它使解析约束变得更容易。允许您以任何顺序指定约束几乎没有什么价值,我可以想象使其成为可能的一些成本(包括机会成本!) 请注意,事实上,规范并不是说如

C#编译器要求最后指定new()约束。 根据MSDN:

当与其他设备一起使用时 约束,新的()约束必须 最后指定


为什么会有这样的限制?

因为在其他约束(例如类)上可以指定构造函数,而在其他约束(例如接口)上则不能


因此,如果new()先出现,然后是接口上的约束,则会出现错误,因为接口上不能有new()约束。

,因为规范这么说。它之所以这么说,可能是因为它使解析约束变得更容易。允许您以任何顺序指定约束几乎没有什么价值,我可以想象使其成为可能的一些成本(包括机会成本!)

请注意,事实上,规范并不是说如果有构造函数约束的话,就必须最后有构造函数约束。它实际上是说,必须按照以下顺序设置约束

  • 主要约束条件
  • 次要约束
  • 构造函数约束
  • 主约束是指指定类型参数必须是引用类型或值类型的约束,次约束是指指定基类或接口的约束,构造函数约束是此处讨论的约束


    本规范的相关章节为§10.1.5,绝对值得一读。

    YAQAPD:关于解析方向的另一个问题

    每种编程语言都有自己的规则。解析的方向就是其中之一。 让我更详细地解释一下(耐心点)

    假设您在Pascal/Delphi中编写以下函数:

    function Sum2Numbers (n1, n2:integer) : integer;
    begin
       result:=n1+n2;
    end;
    
    现在,在C中使用相同的函数:

    int function Sum2Numbers (int n1, int n2)
    {
      return (n1+n2);
    }
    
    从程序员的角度来看,这两个函数做的事情是一样的(事实上也是一样的)。 然而,在幕后,每个编译器都以自己的方式工作

    Pascal/Delphi和许多其他语言通过从左到右解析文本来编译代码。 因此,当我们在Pascal或Delphi中调用函数时,编译器将其放入堆栈中,第一个
    n1
    ,第二个
    n2
    。 C中的相同函数是从右向左执行的,即编译器放入堆栈,第一个
    n2
    ,第二个
    n1

    这两个编译器都按照它们知道的顺序从堆栈中读取参数,所以一切正常

    所有的“C族”语言(C,C++,管理C++,C++ + CLI,C…),它们使用代码解析的左到右顺序。 这就是为什么必须在约束列表的最右侧指定

    new()
    约束的原因。

    在使用类之前,编译器必须事先知道需要创建类的实例

    但是您可以有一个约束,即类型参数实现一个接口,并且有一个空构造函数,因此我认为该参数在这里不适用。是的,您是对的,但是您无法验证这一点,除非new()位于实现接口的类之后(因此将new()约束放在最后)请记住,约束适用于类型参数。因此,完全有可能定义语法,以便
    其中T:new(),IInterface
    意味着
    T
    是一种具有默认构造函数并实现接口的类型
    IInterface
    ,语言设计者只是选择了不以这种方式设计语言。这听起来似乎很容易验证约束可能是真正的原因,我相信你可以按任何顺序来做,但一些可预测性使事情变得更容易。@jonezy:是的,这也是我的猜测(见我的答案)@empi:在编写语法规范时,我认为在混合三类语言结构的同时保证一个项目的唯一性有点困难。说它排在最后是一个简单而优雅的解决方案。在定义XML模式时,您将遇到相同的问题和相同类型的解决方案。事实上,建议的功能会有成本,但好处很少,机会成本也很高。机会成本不仅仅是花费在该功能上的时间被其他有价值的功能所占用;而且,任何时候我们允许语法发生变化,这使得将来扩展或修改该语法变得更加困难。有这么多可能的错误,特别是当存在值类型约束时。这个答案在我看来毫无意义。你的声明有任何来源吗?