首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么声明(j++)是被禁止的?

为什么声明(j++)是被禁止的?
EN

Stack Overflow用户
提问于 2015-12-22 18:24:10
回答 3查看 10.6K关注 0票数 170

下面的代码是错误的(请参阅on ideone):

代码语言:javascript
复制
public class Test
{
    public static void Main()
    {
        int j = 5;
        (j++);      // if we remove the "(" and ")" then this compiles fine.
    }
}

错误CS0201:只有赋值、调用、增量、递减、等待和新的对象表达式可以用作语句。

  1. 当我们删除括号时,为什么代码要编译?
  2. 为什么它不使用括号进行编译?
  3. 为什么C#是这样设计的?
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-12-22 20:56:05

深刻的洞察力得到赏识。

我会尽力而为。

正如其他答案所指出的,这里所做的是编译器正在检测一个表达式是否被用作语句。在许多语言中-- C、JavaScript和许多其他语言--使用表达式作为语句是完全合法的。2 + 2;在这些语言中是合法的,尽管这是一种没有效果的语句。有些表达式只对它们的值有用,有些表达式只对它们的副作用有用(例如调用一个空返回方法),而有些表达式不幸地对两者都有用。(类似于增量。)

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

旁白:人们通常认为对象构造是用于它产生的值,而不是用于构造的副作用;在我看来,允许new Foo();有点错误。特别是,我在现实世界的代码中看到了这种模式,这种模式造成了安全缺陷:

代码语言:javascript
复制
catch(FooException ex) { new BarException(ex); } 

如果代码是复杂的,那么很难发现这个缺陷。

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

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

现在,所有这些,实际上有一些奇怪的情况,C#规范确实暗示或直接声明括号是不允许的,但是C#编译器允许它们。在几乎所有这些情况下,指定的行为和允许的行为之间的微小差异是完全无害的,因此编译器编写人员从未修复过这些小错误。你可以在这里读到这些:

Is there a difference between return myVar vs. return (myVar)?

票数 222
EN

Stack Overflow用户

发布于 2015-12-22 18:30:34

C# language specification

表达式语句用于计算表达式。可用作语句的表达式包括方法调用、使用新运算符的对象分配、使用=和复合赋值运算符的赋值、使用++和--运算符的增量和递减操作以及等待表达式。

在语句周围插入括号将创建一个新的称为括号大小的表达式。从规范中:

括号大小的表达式由括在括号中的表达式组成...。括号大小的表达式是通过计算括号内的表达式来计算的。如果括号内的表达式表示名称空间或类型,则会发生编译时错误。否则,圆括号表达式的结果是对包含的表达式进行计算的结果。

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

票数 46
EN

Stack Overflow用户

发布于 2015-12-22 18:34:22

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

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

代码语言:javascript
复制
int j = 5;
j+1; 

第二行没有效果(但您可能没有注意到)。但是,.it没有删除它(因为不需要代码),而是显式地要求您删除它(因此您会注意到或错误),或者修复它,以防您忘记键入什么。

编辑

使关于支撑的部分变得更清楚。c#中的括号(除了cast和function等其他用途)用于对表达式进行分组,并返回一个表达式(子表达式的构造)。

在那个级别的代码中,只允许使用..。所以

代码语言:javascript
复制
j++; is a valid statement because it produces side effects

但通过使用带括号的元素,您可以将其转换为表达式。

代码语言:javascript
复制
myTempExpression = (j++)

还有这个

代码语言:javascript
复制
myTempExpression;

是无效的,因为编译器无法确定表达式是否具有副作用。(不是不引起停止问题)。

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34422168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档