繁体   English   中英

正确评估表达

[英]Correct evaluation of expression

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

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

编辑顺便说一下,不是从内向外评估的表情? 在这种情况下,在对value.ToUpper()的调用之后检查value!= null的意义何在?它将抛出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";

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

看来该方法旨在处理来自checkbox HTML元素的值。 如果未为复选框指定任何值,则默认情况下它将使用值"on" 如果未选中此复选框,则表单数据中根本没有任何值,因此从Request.Form读取键将提供空引用。

在这种情况下,该方法是正确的,尽管由于使用if-condition-then-true-else-false反模式而非常可怕。 同样,应该给它一个更适合其特定用途的名称,例如GetCheckboxValue

您对该方法的重写是正确无误的。 由于该值不依赖于区域性,因此将值转换为大写不应使用当前的区域性。 因此,一个比您建议的重写甚至更好的重写将是:

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

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

顺便说一句,不是从内到外对表达式求值吗?

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

但是,仅在使用条件表达式的第二和第三操作数的情况下才对其求值,因此从外部和内部对表达式进行求值。 首先评估最外面的条件,以决定将评估哪个操作数。

无论是在重写还是断言这种简洁的做法都是不好的,因为它会导致混乱,您是正确的。

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

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

[[[]]]中的位是三进制表达式的第一个结果,当第一个条件为true时将对其求值,因此您在读/断言它是正确的

但其丑陋如地狱,在当前状态下非常难以读取/无法维护。 我一定会将其更改为您的最后建议

边注:

做的人

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

代替

 return X;

应该拿出来开枪;-)

您在寻找速度或可读性和组织性吗? 执行速度快,示例简短,可能是最好的选择。

再花几毫秒的时间,您可以像下面这样重新编写此实用程序方法作为扩展方法:

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();
}

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

[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

我阅读原始表达的方式与您相同。 因此,我认为您的简短表达是正确的。 如果value为null,它将永远不会达到第二个条件,因此对我来说看起来很安全。

我也讨厌这样的构造:

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

如您所见,这是一种漫长而复杂的(更不用说愚蠢的)写作方式:

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

您的主张很好,简短而正确。

另一种选择:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM