[英]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.