正确评估表达

时间:2009-04-20 13:49:43

标签: c# expression

我在其他人的代码中遇到了以下表达式。我认为这是一个很糟糕的代码有很多原因(尤其是因为它没有考虑到bool.TrueString和bool.FalseString),但我很好奇编译器将如何评估它。

private bool GetBoolValue(string value)
{
    return value != null ? value.ToUpper() == "ON" ? true : false : false;
}

修改 顺便说一下,不是从内向外评估的表达式吗?在这种情况下,在调用value.ToUpper()之后检查值是什么意思!= null会抛出空引用异常?

我认为以下是一个正确(故意)冗长的版本(我永远不会这样说:D):

if (value != null)
{
    if (value.ToUpper() == "ON") 
    {
        return true;
    }
    else        // this else is actually pointless
    {
        return false;
    }
}
else
{
    return false;
}

可以缩短为:

return value != null && value.ToUpper == "ON";

这是对表达式的正确重写吗?

7 个答案:

答案 0 :(得分:4)

看起来该方法被用来处理来自checkbox HTML元素的值。如果没有为复选框指定值,则默认情况下使用值"on"。如果未选中该复选框,则表单数据中没有任何值,因此从Request.Form读取密钥会给出空引用。

在这种情况下,该方法是正确的,但由于使用了if-condition-then-true-else-false反模式,因此它非常可怕。此外,它应该被赋予更适合其特定用途的名称,例如GetCheckboxValue

您重写的方法是正确和合理的。由于该值不依赖于文化,因此将值转换为大写不应使用当前文化。因此,重写甚至比您提议的重写要好一些:

return value != null && value.ToUpperInvariant == "ON";

(与文化无关的方法也比使用特定文化的方法快一点,因此没有理由不使用它们。)

  

顺便说一下,不是表达方式   从内向外评估?

如果是方法调用以便实际评估所有表达式,则必须进行内部调用以评估外部调用的参数。

但是,条件表达式的第二个和第三个操作数仅在使用它们时才会被计算,因此表达式将从外部和内部进行计算。首先评估最外层条件,以决定它将评估哪个操作数。

答案 1 :(得分:3)

你是正确的,无论是在你的改写还是你的断言中,这种简洁的尝试都是不好的,因为它会导致混乱。

答案 2 :(得分:2)

第一个是双嵌套三元运算符

return (value != null) ? [[[value.ToUpper() == "ON" ? true : false]]] : false;

[[[]]中的位是得到评估的三元表达式的第一个结果 当第一个条件为真时,你正在阅读/断言它是正确的

但它的丑陋如同在当前状态下非常难以理解/无法维持。 我肯定会把它改成你的最后一个建议

旁注:

做过的人

if(X == true) 
   return true;
else
   return false;

而不是

 return X;

应该被取出并拍摄; - )

答案 3 :(得分:1)

您在寻找速度,可读性和组织吗?执行速度,缩短的例子可能是最好的方法。

再过几毫秒,您可以将此实用程序方法重写为扩展方法,如下所示:

public static bool ToBoolean(this string value)
{

    // Exit now if no value is set
    if (string.IsNullOrEmpty(value)) return false;

    switch (value.ToUpperInvariant())
    {
        case "ON":
        case "TRUE":
            return true;
    }

    return false;

}

...然后你会按如下方式使用它:

public static void TestMethod()
{
    bool s = "Test".ToBoolean();
}

编辑: 实际上,我错了......快速的性能测试表明扩展方法比内联方法更快。我的测试来源如下,以及我电脑上的输出。

[Test]
public void Perf()
{

    var testValues = new string[] {"true", "On", "test", "FaLsE", "Bogus", ""};
    var rdm = new Random();
    int RunCount = 100000;
    bool b;
    string s;

    Stopwatch sw = Stopwatch.StartNew();
    for (var i=0; i<RunCount; i++)
    {
        s = testValues[rdm.Next(0, testValues.Length - 1)];
        b = s.ToBoolean();
    }
    Console.Out.WriteLine("Method 1: {0}ms", sw.ElapsedMilliseconds);

    sw = Stopwatch.StartNew();
    for (var i = 0; i < RunCount; i++)
    {
        s = testValues[rdm.Next(0, testValues.Length - 1)];
        b = s != null ? s.ToUpperInvariant() == "ON" ? true : s.ToUpperInvariant() == "TRUE" ? true : false : false;
    }
    Console.Out.WriteLine("Method 2: {0}ms", sw.ElapsedMilliseconds);


}

输出:

Method 1: 21ms
Method 2: 30ms

答案 4 :(得分:0)

我以同样的方式阅读原始表达。所以我认为你缩短的表达是正确的。如果value为null,它将永远不会达到第二个条件,所以对我来说看起来很安全。

答案 5 :(得分:0)

我也讨厌像

这样的结构
if (value.ToUpper() == "ON") 
{
    return true;
}
else        // this else is actually pointless
{
    return false;
}

正如您所注意到的那样,这是一种漫长而复杂的(并非愚蠢的)写作方式:

return value.ToUpper() == "ON";

你的命题很好,简短而正确。

答案 6 :(得分:0)

另一种选择:

return string.Equals( value, "ON", StringComparison.OrdinalIgnoreCase );