为什么if语句表达式不被视为条件?

时间:2012-11-01 14:34:13

标签: c# nullreferenceexception

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

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

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

if(cmbDateSelecter.SelectedItem == null)

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

3 个答案:

答案 0 :(得分:6)

它不会在投掷之前评估所有条件,因为在{C#(以及几乎所有其他编程语言)中,logical OR operator执行short-circuit evaluation。即使 对它们进行了评估,它仍会仍然抛出,因为评估前两个条件中的任何一个都涉及尝试访问null对象。所以这种行为不会提供解决方案。

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

答案 1 :(得分:2)

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

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

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

if (cmbDateSelector.SelectedIndex <= 0)
{
    ... nothing selected ...
}

答案 2 :(得分:1)

if语句的括号内的表达式只是类型bool的正常表达式。这不是条件清单。

您似乎错误地介绍了if语句。它不是一个特例 - 它是一个通用案例的实例:C#中接受表达式的语句,然后用评估表达式的结果做一些事情。其他例子是:

  • return expression; - 将返回表达式的值
  • 只要表达式保持while (expression) statement;
  • true就会执行语句 只要表达式保持为true,
  • do statement; while (expression);就会执行语句,但至少执行一次,即使表达式从false开始。

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

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

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

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

if (a || b)

这将首先评估a。如果a为真,则评估停止。仅当a为false时才会b进行评估。尽管如此,

if (NotGood() || b)

将抛出异常,永远不会评估b


P.S。我使用的系统对“条件”有不同的语义。特别地,规则引擎和其他这样的系统处理系统行为的声明形式。这样的系统可以做并行处理条件的所有部分,甚至将异常作为值处理,可能是false