簡體   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