在短路| =和&安培; =赋值运算符在C# [英] Short circuit on |= and &= assignment operators in C#

查看:103
本文介绍了在短路| =和&安培; =赋值运算符在C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 || &放大器;&安培; 被定义为短路运营商在C#和这种行为是由语言规范保证,但做 | = &安培; = 短路太

I know that || and && are defined as short-circuit operators in C#, and such behaviour is guaranteed by the language specification, but do |= and &= short-circuit too?

例如:

private bool IsEven(int n)
{
    return n % 2 == 0;
}

private void Main()
{
    var numbers = new int[] { 2, 4, 6, 8, 9, 10, 14, 16, 17, 18, 20 };

    bool allEven = true;
    bool anyOdd = false;

    for (int i = 0; i < numbers.Length; i++)
    {
        allEven &= IsEven(numbers[i]);
        anyOdd |= !IsEven(numbers[i]);
    }
}

在9项灾区, allEven 为假,这意味着所有后续条目是不相关的 - allEven 是保证为到前pression所有将来调用假的。这同样适用于 anyOdd ,它被设置为true时,看到9,而且将继续适用于所有后续调用到前pression。

When the 9 entry is hit, allEven becomes false, meaning that all subsequent entries are irrelevant - the value of allEven is guaranteed to be false for all future calls to that expression. The same goes for anyOdd, which is set to true when it sees 9, and will remain true for all subsequent calls to that expression.

那么,做&安培; = | = 快捷方式,或者说是 ISEVEN 保证在每个迭代上被称为?有没有在这种情况下,语言规范定义的任何行为?是否有任何角落情况下,这种短路会产生问题?

So, do &= and |= shortcut, or is IsEven guaranteed to be called on every iteration? Is there any defined behaviour in the language specification for this case? Are there any corner-cases where such short circuiting would be problematic?

推荐答案

C#的规范保证双方都从准确评估一次左到右,并且没有短路发生。

The C# specification guarantees that both sides are evaluated exactly once from left-to-right and that no short-circuiting occurs.

为前pressions 5.3.3.21一般规则嵌入前pressions

5.3.3.21 General rules for expressions with embedded expressions

以下规则适用于这些类型的前pressions的:括号内的前pressions(§7.6.3),元素访问前pressions(第7.6.6节),基本访问前$ P $与索引pssions(§7.6.8),增量和减量前pressions(§7.6.9,第7.7.5节),铸造前pressions(§7.7.6),一元+, - ,〜, *前pressions,二元+, - ,*,/,%,&LT;!&LT;,>>,&LT中,&lt; =,>,> =,= =,=,是因为,和放大器; ,|,^前pressions(§7.8,§7.9,§7.10,§7.11),复合赋值前pressions(§7.17.2),选中和未选中前pressions(§7.6.12),加上阵列和委托创建前pressions(§7.6.10)。

The following rules apply to these kinds of expressions: parenthesized expressions (§7.6.3), element access expressions (§7.6.6), base access expressions with indexing (§7.6.8), increment and decrement expressions (§7.6.9, §7.7.5), cast expressions (§7.7.6), unary +, -, ~, * expressions, binary +, -, *, /, %, <<, >>, <, <=, >, >=, ==, !=, is, as, &, |, ^ expressions (§7.8, §7.9, §7.10, §7.11), compound assignment expressions (§7.17.2), checked and unchecked expressions (§7.6.12), plus array and delegate creation expressions (§7.6.10).

每个这些前pressions有一个或多个子-EX pressions是的无条件评估在一个固定的顺序。

Each of these expressions has one or more sub-expressions that are unconditionally evaluated in a fixed order.

对于复合运算符的C#规范说:

The C# specification for compound operators says:

7.17.2复合赋值

...

表格 X OP = Y 的操作是通过应用二元运算符重载解析(§7.3.4)作为操作是否被写入 X OP是。然后,

An operation of the form x op= y is processed by applying binary operator overload resolution (§7.3.4) as if the operation was written x op y. Then,


      
  • 如果选定的运算符的返回类型隐式转换为类型X ,则运算按 X = X OP是,但 X 只计算一次。

  • If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.

否则,如果选定的运算符是predefined运营商,如果选择的运算符的返回类型是显式转换为 X 的类型,如果隐式转换为类型X 或运算符是移位运算符,则操作进行评估为 X =(T)(X运算Y),其中T是类型X ,但 X 只计算一次。

Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y), where T is the type of x, except that x is evaluated only once.

...

在你的情况&安培; | 。该短路行为将镜像的&安培; / | ,而不是&放大器;&安培; / ||

In your case op is & or |. The short circuiting behavior mirrors that of &/| and not &&/||.

请注意,这仅仅是指行为单线程的情况可见。因此,如果在右侧没有副作用是在这样的情况下可观察到的,编译器或抖动仍然可以自由地省略评价

Note that this only refers to behavior visible in a single threaded scenario. So if the right hand side has no side-effects that are observable in such a scenario, the compiler or JITter is still free to omit the evaluation.

在您的示例,编译器可以自由地终止循环一旦知悉的结果,因为没有这样的副作用。但它并不需要这么做。

In your example the compiler is free to terminate the loop once it knows the result, since there are no such side-effects. But it's not required to do so.

在特定的时间不能算作这样的副作用,你因此不能依靠不断有你运行code。这可以在一个安全上下文有问题的,因为它可以引入一个定时副信道

In particular timing does not count as such a side-effect, and you thus can't rely on your code having constant runtime. This can be problematic in a security context, since it can introduce a timing side-channel.

这篇关于在短路| =和&安培; =赋值运算符在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆