简体   繁体   English

正确评估表达

[英]Correct evaluation of expression

I came across the following expression in someone else's code. 我在别人的代码中遇到了以下表达式。 I think it's terrible code for a number of reasons (not least because it fails to take into account bool.TrueString and bool.FalseString), but am curious as to how the compiler will evaluate it. 我认为这是很糟糕的代码,其原因有很多(特别是因为它没有考虑到bool.TrueString和bool.FalseString),但对于编译器如何评估它感到好奇。

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

Edit Incidentally, aren't the expressions evaluated from the inside-outwards? 编辑顺便说一下,不是从内向外评估的表情? In this case, what's the point of checking for value != null after the call to value.ToUpper() which will throw a null reference exception? 在这种情况下,在对value.ToUpper()的调用之后检查value!= null的意义何在?它将抛出null引用异常?

I think the following is a correct (deliberately) verbose version (I'd never leave it like this :D ): 我认为以下是正确的(故意的)详细版本(我永远不会像这样:D):

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

Which can be shortened to: 可以缩短为:

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

Is this a correct re-writing of the expression? 这是对表达式的正确重写吗?

It looks like the method is indended to handle a value that comes from a checkbox HTML element. 看来该方法旨在处理来自checkbox HTML元素的值。 If no value is specified for the checkbox, it uses the value "on" by default. 如果未为复选框指定任何值,则默认情况下它将使用值"on" If the checkbox is not checked there is no value at all from it in the form data, so reading the key from Request.Form gives a null reference. 如果未选中此复选框,则表单数据中根本没有任何值,因此从Request.Form读取键将提供空引用。

In this context the method is correct, althought it's quite horrible due to the use of the if-condition-then-true-else-false anti-pattern. 在这种情况下,该方法是正确的,尽管由于使用if-condition-then-true-else-false反模式而非常可怕。 Also it should have been given a name that is more fitting for it's specific use, like GetCheckboxValue . 同样,应该给它一个更适合其特定用途的名称,例如GetCheckboxValue

Your rewrite of the method is correct and sound. 您对该方法的重写是正确无误的。 As the value is not culture dependant, converting the value to uppercase should not use the current culture. 由于该值不依赖于区域性,因此将值转换为大写不应使用当前的区域性。 So a rewrite that is even slightly better than the one that you proposed would be: 因此,一个比您建议的重写甚至更好的重写将是:

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

(The culture independent methods are also a bit faster than the ones using a specific culture, so there is no reason not to use them.) (与文化无关的方法也比使用特定文化的方法要快一些,因此没有理由不使用它们。)

Incidentally, aren't the expressions evaluated from the inside-outwards? 顺便说一句,不是从内到外对表达式求值吗?

If it was method calls so that all expressions were actually evaluated, they would, as the inner call has to be made to evaluate the parameters for the outer call. 如果是方法调用,以便实际上对所有表达式进行求值,则必须进行内部调用,以评估外部调用的参数。

However, the second and third operands of the conditional expression is only evaluated if they are used, so the expressions are evaluated from the outside and inwards. 但是,仅在使用条件表达式的第二和第三操作数的情况下才对其求值,因此从外部和内部对表达式进行求值。 The outermost condition is evaluated first to decide which of the operands it will evaluate. 首先评估最外面的条件,以决定将评估哪个操作数。

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

well the first one is a double-nested ternary operator 好,第一个是双嵌套三元运算符

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

The bit in [[[ ]]] is the first result of the ternary expression which gets evaluated when the first condition is true so you're reading/assertion of it is correct [[[]]]中的位是三进制表达式的第一个结果,当第一个条件为true时将对其求值,因此您在读/断言它是正确的

but its ugly as hell and very unreadable/unmaintainable in its current state. 但其丑陋如地狱,在当前状态下非常难以读取/无法维护。 I'd definitely change it to your last suggestion 我一定会将其更改为您的最后建议

SideNote: 边注:

People who do 做的人

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

instead of 代替

 return X;

should be taken out and shot ;-) 应该拿出来开枪;-)

Are you looking for speed or readability and organization? 您在寻找速度或可读性和组织性吗? Speed of execution, your shortened example is probably the best way to go. 执行速度快,示例简短,可能是最好的选择。

For a few extra milliseconds, you could re-write this utility method as an extension method like so: 再花几毫秒的时间,您可以像下面这样重新编写此实用程序方法作为扩展方法:

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;

}

... and then you would use it as follows: ...然后您将按以下方式使用它:

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

EDIT: Actually, I'm wrong... a quick performance test shows that the extension method is FASTER than the inline method. 编辑:实际上,我错了...快速性能测试表明,扩展方法比内联方法更快 The source of my test is below, as well as the output on my PC. 下面是我的测试源以及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);


}

Output: 输出:

Method 1: 21ms
Method 2: 30ms

I read the original expression the same way you do. 我阅读原始表达的方式与您相同。 So I think your shortened expression is correct. 因此,我认为您的简短表达是正确的。 If value is null it will never get to the second conditional, so it looks safe to me. 如果value为null,它将永远不会达到第二个条件,因此对我来说看起来很安全。

I also hate the constructs like: 我也讨厌这样的构造:

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

as you noticed it is a long and convoluted (not to say stupid) way of writing: 如您所见,这是一种漫长而复杂的(更不用说愚蠢的)写作方式:

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

Your proposition is nice, short and correct. 您的主张很好,简短而正确。

另一种选择:

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

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

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