C#中的行为和评估顺序

Naw*_*waz 5 c# operator-precedence undefined-behavior

可能重复:
C#:功能评估顺序(vs C)

代码段:

i += ++i;
a[++i] = i;
int result =  fun() - gun();
//statement of similar kind
Run Code Online (Sandbox Code Playgroud)

他们的行为在C#中定义得很好吗?在C++中,此类代码调用未定义/未指定的行为.还请在回复中引用语言规范中的相关部分!

Mar*_*ell 11

这里的关键是"1.4表达式"中的表,以及"7.3.1运算符优先级和关联性".我不会从1.4复制表,而是引用7.3.1:

  • 除赋值运算符外,所有二元运算符都是左关联运算符,这意味着操作从左到右执行.例如,x + y + z被评估为(x + y)+ z.
  • 赋值运算符和条件运算符(?:)是右关联的,这意味着操作从右到左执行.例如,x = y = z被评估为x =(y = z).

第一个是逻辑扩展(或:使用关联性规则):

i = i + ++i;
Run Code Online (Sandbox Code Playgroud)

在这里,顺序(从表中)是预增量,然后是加法,然后是赋值 - 所以我们应该期望i加倍加1.事实上,i=6我们按预期得到13分.

a[++i] = i;
Run Code Online (Sandbox Code Playgroud)

再次从表中,顺序应该是数组访问,预增量,赋值 - 所以我希望第i + 1个值为i + 1.确实,检查:

    int[] a = { 0, 0, 0, 0, 0 };
    int i = 2;
    a[++i] = i;
Run Code Online (Sandbox Code Playgroud)

我们确实得到了{0, 0, 0, 3, 0}.

最后,方法调用优先于减法,然后是从左到右; 所以它应该是fun(),gun(),-,的分配.


Eri*_*ert 10

人们总是这么困惑,这很不幸,因为在C#中它非常简单.规则是:

  • 从执行的线程,周期,故事结束观察时,观察到子表达式从左到右进行评估.(如果某个其他线程正在观察副作用,则允许观察其他线程的评估顺序不同.)

  • 运算符执行的顺序取决于它们的优先级和关联性.

这是唯一的两个相关规则,它们完全定义了您提供的代码的行为.在

i += ++i; 
Run Code Online (Sandbox Code Playgroud)

首先评估i,然后评估++ i,然后执行+ =.

a[++i] = i; 
Run Code Online (Sandbox Code Playgroud)

首先计算'a',然后评估++ i,然后运行索引运算符,然后计算i,然后进行赋值.

int result =  fun() - gun(); 
Run Code Online (Sandbox Code Playgroud)

第一个结果被评估,然后有趣,然后枪,然后减法,然后分配.

还请在回复中引用语言规范中的相关部分!

你完全有能力查看目录.这不难发现.

  • @leppie:也许这会让你感觉更好.在"A().B().C [D()]中.E = F();" 字段E的评估必须在函数调用F()的评估之前进行.为了评估字段E以确定其位置,我们必须首先评估A(),B(),C(),D()并执行索引运算符.**在右侧**之前评估作业的左侧.评估它以确定右侧将要分配的*位置*. (5认同)
  • @leppie:它没有被评估变量的*内容*,它被评估为*location*.内容是无关紧要的,但是如何在不评估左侧的情况下找出作业的位置?我的观点是左侧的评估发生在*右侧之前*:在C#中,子表达式总是从左到右评估**并且包括子表达式,例如被评估的局部变量以确定它们的地址. (2认同)
  • 谢谢,清楚的例子:) (2认同)