C# 为什么会这样说(j+;+;);被禁止的

C# 为什么会这样说(j+;+;);被禁止的,c#,syntax,expression,language-design,parentheses,C#,Syntax,Expression,Language Design,Parentheses,以下代码错误(请参见): 错误CS0201:仅分配、调用、递增、递减、等待和 新的对象表达式可以用作语句 为什么删除括号时代码会编译 为什么它不使用括号编译 为什么C#是这样设计的 在 表达式语句用于计算表达式。可以用作语句的表达式包括方法调用、使用new运算符的对象分配、使用=和复合赋值运算符的赋值、使用++和--运算符的递增和递减操作以及等待表达式 在语句周围加上括号将创建一个新的所谓括号表达式。根据规范: 括号内的表达式由括号内的表达式组成。。。通过计算括号内的表达式来计算括号内的表达式。

以下代码错误(请参见):

错误CS0201:仅分配、调用、递增、递减、等待和 新的对象表达式可以用作语句

  • 为什么删除括号时代码会编译
  • 为什么它不使用括号编译
  • 为什么C#是这样设计的
  • 表达式语句用于计算表达式。可以用作语句的表达式包括方法调用、使用new运算符的对象分配、使用=和复合赋值运算符的赋值、使用++和--运算符的递增和递减操作以及等待表达式

    在语句周围加上括号将创建一个新的所谓括号表达式。根据规范:

    括号内的表达式由括号内的表达式组成。。。通过计算括号内的表达式来计算括号内的表达式。如果括号内的表达式表示命名空间或类型,则会发生编译时错误。否则,带括号表达式的结果就是所包含表达式的求值结果


    由于括号内的表达式未列为有效的表达式语句,因此根据规范,它不是有效的语句。设计者为什么选择这样做是任何人的猜测,但我打赌是因为如果整个语句都包含在括号中,括号就没有任何用处:
    stmt
    (stmt)
    完全相同。

    因为
    i++
    周围的括号正在创建/定义表达式。。正如错误消息所说。。简单表达式不能用作语句

    为什么语言设计成这样?为了防止错误,使用误导性的表达式作为语句,不会产生代码那样的副作用

    int j = 5;
    j+1; 
    
    第二行没有效果(但您可能没有注意到)。但是,它不是让编译器删除它(因为不需要代码),而是显式地要求您删除它(这样您就会知道错误),或者在您忘记键入某些内容时修复它

    编辑

    为了让关于bracked的部分更清楚。。c#中的括号(除了其他用途,如cast和函数调用)用于对表达式进行分组,并返回单个表达式(由子表达式组成)

    在该级别的代码中,只允许使用语句。。所以

    j++; is a valid statement because it produces side effects
    
    但是通过使用带括号的,你将它变成了一个表达式

    myTempExpression = (j++)
    
    还有这个

    myTempExpression;
    
    无效,因为编译器无法将该表达式作为副作用进行测量。(并非没有引起停止问题)

    深刻的见解受到赞赏

    我会尽力的

    正如其他答案所指出的,这里发生的事情是编译器检测到一个表达式被用作语句。在许多语言中——C、JavaScript和许多其他语言——将表达式用作语句是完全合法的<代码>2+2在这些语言中是合法的,即使这是一条无效的语句。有些表达式仅对其值有用,有些表达式仅对其副作用有用(例如对void返回方法的调用),不幸的是,有些表达式对两者都有用。(比如增量。)

    要点是:只包含表达式的语句几乎肯定是错误的,除非这些表达式通常被认为对其副作用比其值更有用。C#设计师希望找到一个中间立场,允许那些通常被认为是副作用的表达,而不允许那些通常被认为对他们的价值有用的表达。他们在C#1.0中确定的一组表达式是递增、递减、方法调用、赋值,还有一些有争议的构造函数调用


    旁白:人们通常认为一个对象的构造是用于它产生的价值,而不是用于构造的副作用;在我看来,允许
    newfoo()有点不符合功能。特别是,我在实际代码中看到了这种模式,它导致了安全缺陷:

    catch(FooException ex) { new BarException(ex); } 
    
    如果代码很复杂,那么很难发现这个缺陷


    因此,编译器可以检测由不在该列表中的表达式组成的所有语句。特别是,圆括号表达式被标识为圆括号表达式。它们不在“允许作为语句表达式”列表中,因此它们是不允许的

    所有这些都是为C语言的设计原则服务的如果键入
    (x++)您可能做错了什么。这可能是
    M(x++)的输入错误或其他一些正义的东西。请记住,C#编译器团队的态度不是“我们能想出一些方法让它工作吗?”C#编译器团队的态度是“如果看似合理的代码看起来像是一个可能的错误,让我们通知开发人员”。C#开发者喜欢这种态度

    现在,尽管如此,实际上还是有一些奇怪的情况,C#规范确实暗示或直接声明不允许使用括号,但C#编译器无论如何都允许使用括号。在几乎所有这些情况下,指定行为和允许行为之间的微小差异是完全无害的,因此编译器编写人员从未修复过这些小错误。您可以在此处阅读这些内容:


    @Servy很多参与C语言设计的人都是如此,这就是我问的原因。这有什么问题吗?我无法想象一个比“为什么一种特定的编程语言以这种方式处理这种特定的行为?”更具主题性的问题了。现在我们有了Eric Lippert的答案。也许你想重新考虑一下你对被接受答案的决定。今天是圣诞节,所以也许你接受这个答案太早了。@Servy你明白吗
    catch(FooException ex) { new BarException(ex); }