【问题标题】:Is order guaranteed in an or expression [duplicate]是否在 or 表达式中保证顺序[重复]
【发布时间】:2016-07-26 16:03:09
【问题描述】:

我有这样的表达方式:

EqualByComparer comparer;
if (ListEqualByComparer.TryGetOrCreate(x, y, out comparer) ||
    EnumerableEqualByComparer.TryGetOrCreate(x, y, out comparer))
{
    return comparer.Equals(x, y, compareItem, settings, referencePairs);
}

ListEqualByComparer.TryGetOrCreate 是否总是在 EnumerableEqualByComparer.TryGetOrCreate 之前被调用?

【问题讨论】:

  • 是的,如果返回true,则不会调用EnumerableEqualByComparer.TryGetOrCreate(x, y, out comparer)(短路评估)
  • 另见Operator || - 在if (x || y) 中保证x 将被检查(首先)。如果xtrue,则y不会被评估。
  • 我相信是这样,这个确切的上下文就是它的原因。代码以这种方式编译以节省内存,如果第一个条件为真,则不必评估第二个条件
  • 抱歉骗了我,我搜索了但失败了。
  • 请注意,序列是固定的并且仅在必要时才调用第二个条件这一事实通常既重要又有用。我经常写if (foo == null || foo.bar())之类的条件

标签: c# operator-precedence


【解决方案1】:

ListEqualByComparer.TryGetOrCreate 是否总是在 EnumerableEqualByComparer.TryGetOrCreate 之前被调用?

是的,因为|| 是短路的,所以只有在第一次调用返回false 时才会进行第二次调用。

来自 C# 5 规范,第 7.12.1 节:

&&|| 的操作数是bool 类型时,或者当操作数的类型未定义适用的operator &operator |,但确实定义了到@987654330 的隐式转换时@,操作处理如下:

[...]

操作x || y 被评估为x ? true : y。换句话说,x 首先被评估并转换为类型bool。那么,如果x为真,则运算结果为true。否则,y 被求值并转换为类型bool,这将成为操作的结果。

【讨论】:

  • 谢谢,我试图在语言规范中找到它但失败了。
  • @JohanLarsson:已添加规范参考。
  • 一个问题:因为这些是函数调用,是不是意味着函数调用也是从左到右,一个接一个地调用,还是所有函数都按某种顺序调用在评估之前提取操作数?
  • @Veksi:我不确定你在这种情况下的意思。评估操作数意味着在此处调用方法......如果不调用方法,您不能“评估左操作数”,并且该语言保证在评估左操作数之前不会评估右操作数。一般来说,确实保证从左到右的评估,但这对于像Foo(Bar(), Baz())这样的东西更重要
  • @Veksi C++ 在处理内置的 && / II 时具有与 C# 相同的规则,但它确实 notoperator && 重载时提供相同的保证(其中这就是为什么强烈建议您不要超载operator &&)。 OTOH 给定了foo( bar(), baz() ),我很确定 C# 保证 bar 将在 baz 之前被调用,但 C++ 不会。
【解决方案2】:

是的 - 详细信息在 documentation 中。

仅当第一个条件为假时才评估第二个条件

【讨论】:

    【解决方案3】:

    来自 C# 参考 (link):

    条件或运算符 (||) 对其 bool 操作数执行逻辑或。如果第一个操作数的计算结果为 true,则不计算第二个操作数。如果第一个操作数的计算结果为 false,则第二个运算符确定整个 OR 表达式的计算结果是 true 还是 false

    【讨论】:

      【解决方案4】:

      是的,订单有保证。 MSDN 状态:

      逻辑运算符还保证从左到右评估其操作数。但是,它们计算确定表达式结果所需的最少操作数。这称为“短路”评估。因此,表达式的某些操作数可能不会被计算。

      【讨论】:

        猜你喜欢
        • 2010-12-14
        • 2021-07-19
        • 2015-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-13
        • 2014-10-13
        相关资源
        最近更新 更多