1

我有一个组合框,其中包含日期列表。我想确保用户实际选择了一个日期。所以,我有以下内容:

        if (cmbDateSelecter.SelectedItem.ToString().ToLower().Contains("select") || 
            cmbDateSelecter.SelectedItem.ToString().ToLower().Contains("seleccione") || 
            cmbDateSelecter.SelectedItem == null)

默认项目是“选择日期”,所以我正在检查这是否是所选项目。这曾经是自己工作的,出于某种我还没有弄清楚的原因,开始抛出 NullReferenceExceptions。所以,我添加了空检查。但是,我仍然遇到异常。但如果我这样做:

if(cmbDateSelecter.SelectedItem == null)

现在,我知道我可以先进行空检查,一切都会变得很糟糕。我的问题是为什么它在抛出异常之前不评估所有表达式?如果其中一个是真的,在我的表达式的情况下(作为空检查),为什么它仍然会抛出异常?

4

3 回答 3

6

它不会在抛出之前评估所有条件,因为在 C#(以及几乎所有其他编程语言)中,逻辑 OR 运算符进行短路评估。即使它确实评估了它们,它仍然会抛出,因为评估前两个条件中的任何一个都涉及尝试访问空对象。所以这种行为不会提供解决方案。

但是,短路评估正是允许您通过null在开头移动检查来解决问题的方法:如果测试返回true,则编译器知道整个表达式将是true并跳过评估抛出的表达式。

于 2012-11-01T14:36:06.817 回答
2

它从左到右评估并使用短路评估,因此您需要:

if (cmbDateSelecter.SelectedItem == null ||
    cmbDateSelecter.SelectedItem.ToString().ToLower().Contains("select") || 
    cmbDateSelecter.SelectedItem.ToString().ToLower().Contains("seleccione")
)

另一点是您的测试有点脆弱,因为您依赖于“请选择”选项的特定字符串。由于这无疑是第一个选项,您可以改为使用:

if (cmbDateSelector.SelectedIndex <= 0)
{
    ... nothing selected ...
}
于 2012-11-01T14:37:10.490 回答
1

语句括号内的表达式if只是 type 的普通表达式bool。它不是条件列表。

似乎以if错误的方式向您介绍了该声明。这不是一种特殊情况——它是一般情况的一个实例:C# 中的语句接受一个表达式,然后对表达式的求值结果做一些事情。其他例子是:

  • return expression;- 将返回表达式的值
  • while (expression) statement;只要表达式仍然存在,就会执行语句true
  • do statement; while (expression);只要表达式保持为真,就执行语句false,但至少执行一次,即使表达式开始时也是如此。

这些以及更多的共同点是它们都评估表达式以确定其值。如果在表达式求值期间抛出任何异常,则表达式求值立即停止,并开始搜索异常处理程序。

它在所有现代编程语言中几乎都以相同的方式工作,所以这是一个将伴随你一生的课程。

请注意,即使是“短路评估”之类的东西也不会改变这一点:

private bool NotGood(){throw new Exception();}

if (a || b)

这将首先评估a. 如果a为真,则评估停止。只有 if ais false 才会b被评估。仍然,

if (NotGood() || b)

将抛出异常并且永远不会评估b.


PS 我曾使用过对“条件”具有不同语义的系统。特别是,规则引擎和其他此类系统处理系统行为的声明形式。这样的系统可能会做一些事情,比如并行评估条件的所有部分,甚至将异常视为一个值,也许是false.

于 2014-05-16T02:29:28.120 回答