【问题标题】:Unexpected condition result意外状况结果
【发布时间】:2017-12-29 05:30:41
【问题描述】:

我有一个方法:

public bool Exists(int levelId, string name, int excludeSubjectIdInCheck = 0)
{
    return _context.Subjects.Any(subj => subj.LevelId == levelId
        && String.Equals(subj.Name, name, StringComparison.OrdinalIgnoreCase)
        && subj.DeletedAt == null
        && excludeSubjectIdInCheck != 0 ? subj.Id != excludeSubjectIdInCheck : true);
}

这一行的计算结果为真:

subj => subj.LevelId == levelId

这是假的:

String.Equals(subj.Name, name, StringComparison.OrdinalIgnoreCase)

这是真的:

subj.DeletedAt == null

这也是真的:

excludeSubjectIdInCheck != 0 ? subj.Id != excludeSubjectIdInCheck : true

但是,此方法返回 true。为什么是这样?我希望这将返回 false 给定 3 true 和 1 false。但是当我将最后一个条件用括号括起来时:

public bool Exists(int levelId, string name, int excludeSubjectIdInCheck = 0)
{
    return _context.Subjects.Any(subj => subj.LevelId == levelId
        && String.Equals(subj.Name, name, StringComparison.OrdinalIgnoreCase)
        && subj.DeletedAt == null
        && (excludeSubjectIdInCheck != 0 ? subj.Id != excludeSubjectIdInCheck : true));
}

它返回假。但是如果我看一下,括号不应该有任何区别,因为它没有将任何条件分组。这段代码发生了什么?

【问题讨论】:

    标签: c#


    【解决方案1】:

    看来三元运算符的优先级最低。没有任何括号,所有的

    subj.LevelId == levelId
        && String.Equals(subj.Name, name, StringComparison.OrdinalIgnoreCase)
        && subj.DeletedAt == null
        && excludeSubjectIdInCheck != 0
    

    被评估为三元运算符 (?:) 的第一个操作数。然后,该值确定要计算其他两个操作数的哪一部分作为结果。

    这里的教训是始终在复杂的布尔表达式中使用括号,以强制执行您想要的评估。不要依赖默认优先级来避免这样的意外结果。

    注意

    作为布尔表达式操作数的布尔文字几乎总是无关紧要的。我确信有一种方法可以简化您的布尔表达式以完全删除三元运算符。我太累了,现在想都想不透了。我认为这涉及将三元运算符的条件移动到更大表达式的开头。

    【讨论】:

    • 是的,相等,然后是逻辑 &&,然后是条件三元运算符。 Reference
    • 谢谢,我明白现在发生了什么。没想到所有这些都会作为第一个操作数进行评估。感谢您的解释和建议。
    猜你喜欢
    • 2019-05-05
    • 2012-10-09
    • 2018-09-04
    • 2017-06-02
    • 2021-11-11
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    相关资源
    最近更新 更多