三元或不到三?[关闭]
-
03-07-2019 - |
题
我个人的倡导者三操作员:()?:;我认识到,它有它的位置,但是我遇到的许多程序员,是完全反对使用它,而一些,使用它太经常。
你有什么感受吗?有什么有趣的代码你看到使用它吗?
解决方案
仅用于简单表达:
int a = (b > 10) ? c : d;
不要链接或嵌套三元运算符,因为它难以阅读和混淆:
int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;
此外,在使用三元运算符时,请考虑以提高可读性的方式格式化代码:
int a = (b > 10) ? some_value
: another_value;
其他提示
由于无法在每个子表达式上放置断点,因此调试稍微困难一些。我很少用它。
我爱他们,特别是在类型安全的语言中。
我不明白这是怎么回事:
int count = (condition) ? 1 : 0;
比这更难:
int count;
if (condition)
{
count = 1;
}
else
{
count = 0;
}
编辑 -
我认为三元运算符使得所有东西都变得不那么复杂,而且比其他东西更整洁。
链接我很好 - 嵌套,而不是那么多。
我倾向于在C语言中更多地使用它们b / c它们是一个有价值的if语句,所以它减少了不必要的重复或变量:
x = (y < 100) ? "dog" :
(y < 150) ? "cat" :
(y < 300) ? "bar" : "baz";
而不是
if (y < 100) { x = "dog"; }
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; }
else { x = "baz"; }
在这样的作业中,我发现重构并且更清晰。
另一方面,当我在ruby工作时,我更有可能使用if...else...end
,因为它也是一个表达式。
x = if (y < 100) then "dog"
elif (y < 150) then "cat"
elif (y < 300) then "bar"
else "baz"
end
(虽然,诚然,对于这个简单的事情,我可能只是使用三元运算符。)
三元?:
运算符仅仅是程序if
结构的功能等价物。因此,只要您不使用嵌套的<=>表达式,就可以在此处使用/反对任何操作的函数表示的参数。但是嵌套三元操作会导致代码完全混乱(为读者练习:尝试编写一个解析器来处理嵌套的三元条件,你会欣赏它们的复杂性。)
但是在很多情况下保守使用<=>运算符会导致代码实际上更容易读取。例如:
int compareTo(Object object) {
if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) {
return 1;
if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) {
return -1;
else
return 0;
}
现在将其与此进行比较:
int compareTo(Object object) {
if(isLessThan(object))
return reverseOrder ? 1 : -1;
else(isGreaterThan(object))
return reverseOrder ? -1 : 1;
else
return 0;
}
由于代码更紧凑,因此语法噪音更少,并且通过明智地使用三元运算符(仅与 reverseOrder 属性相关),最终结果并不特别简洁。
这是一个问题的风格,真的,潜意识的规则,我倾向于遵循的是:
- 只有评估表达1-所以
foo = (bar > baz) ? true : false
, 但不foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
- 如果我使用它,用于显示逻辑的,例如
<%= (foo) ? "Yes" : "No" %>
只有真正利用它对分配;从来没流逻辑(使永远不会流逻辑中的三本身就是一个谎言,无视这最后一点。(foo) ? FooIsTrue(foo) : FooIsALie(foo)
)
我喜欢它,因为它的简洁和优雅的用于简单分配行动。
像许多意见问题一样,答案是不可避免的:它取决于
类似于:
return x ? "Yes" : "No";
我认为 更简洁(我解析得更快)而不是:
if (x) {
return "Yes";
} else {
return "No";
}
现在如果您的条件表达式很复杂,那么三元运算不是一个好的选择。类似的东西:
x && y && z >= 10 && s.Length == 0 || !foo
不适合三元运营商。
顺便说一句,如果你是C程序员,GCC实际上有一个扩展名,允许您排除三元组的if-true部分,如下所示:
/* 'y' is a char * */
const char *x = y ? : "Not set";
将x
设置为y
,假设NULL
不是<=>。好东西。
在我看来,只有在需要表达式的情况下使用三元运算符才有意义。
在其他情况下,似乎三元运算符会降低清晰度。
通过圈复杂度的衡量标准,使用if
语句或三元运算符是等价的。因此,通过该衡量标准,答案是不,复杂性将与以前完全相同。
通过其他措施,例如可读性,可维护性和干燥(不要重复自己),任何一种选择都可能比其他选择更好。
我经常在我被限制在构造函数中工作的地方使用它 - 例如,新的.NET 3.5 LINQ to XML构造 - 在可选参数为null时定义默认值。
受挫的例子:
var e = new XElement("Something",
param == null ? new XElement("Value", "Default")
: new XElement("Value", param.ToString())
);
或(感谢asterite)
var e = new XElement("Something",
new XElement("Value",
param == null ? "Default"
: param.ToString()
)
);
无论您是否使用三元运算符,确保您的代码可读是重要的。任何构造都可能变得不可读。
我尽可能使用三元运算符,除非它使代码极难阅读,但那通常只是表明我的代码可能会使用一些重构。
有些人认为三元运算符是<!> << hidden <!>功能或有点神秘。这是我开始用C语言编程时学到的第一件事,我认为它根本不会降低可读性。这是该语言的自然组成部分。
我同意jmulder:它不应该用来代替if
,但它有返回表达式或表达式内的位置:
echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;
前者只是一个例子,应该使用更好的i18n复数支持!
(当天的黑客)
#define IF(x) x ?
#define ELSE :
然后你可以做if-then-else作为表达式:
int b = IF(condition1) res1
ELSE IF(condition2) res2
ELSE IF(conditions3) res3
ELSE res4;
如果您使用三元运算符进行简单的条件赋值,我认为没问题。我已经看到它(ab)用于控制程序流程甚至没有进行任务,我认为应该避免。在这些情况下使用if语句。
我认为应该在需要时使用三元运算符。这显然是一个非常主观的选择,但我发现一个简单的表达式(特别是一个返回表达式)比完整的测试更清晰。 C / C ++中的示例:
return (a>0)?a:0;
与:相比:
if(a>0) return a;
else return 0;
您还可以在三元运算符和创建函数之间找到解决方案。例如在Python中:
l = [ i if i > 0 else 0 for i in lst ]
替代方案是:
def cap(value):
if value > 0:
return value
return 0
l = [ cap(i) for i in lst ]
在Python(例如)中,需要经常看到这样的习语:
l = [ ((i>0 and [i]) or [0])[0] for i in lst ]
这一行使用Python中逻辑运算符的属性:它们是惰性的,如果它等于最终状态,则返回计算的最后一个值。
我喜欢他们。我不知道为什么,但是当我使用三元表达式时,我觉得非常酷。
我见过这样的野兽(它实际上更糟糕了,因为它是isValidDate并且每月和每天都进行检查,但我不会为了记住整件事而烦恼):
isLeapYear =
((yyyy % 400) == 0)
? 1
: ((yyyy % 100) == 0)
? 0
: ((yyyy % 4) == 0)
? 1
: 0;
明显地,一系列if语句会更好(虽然这个比我曾经看过的宏版本更好)。
我不介意这样的小事:
reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age;
甚至是一些棘手的事情:
printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s");
我喜欢在调试代码中使用运算符来打印错误值,所以我不必一直查找它们。通常我这样做的调试打印一旦我完成开发就不会保留。
int result = do_something();
if( result != 0 )
{
debug_printf("Error while doing something, code %x (%s)\n", result,
result == 7 ? "ERROR_YES" :
result == 8 ? "ERROR_NO" :
result == 9 ? "ERROR_FILE_NOT_FOUND" :
"Unknown");
}
我几乎从不使用三元运算符,因为每当我使用它时,它总是让我想到的比以后当我尝试维护它时要多得多。
我喜欢避免冗长,但是当它使代码更容易上手时,我会为冗长而努力。
考虑:
String name = firstName;
if (middleName != null) {
name += " " + middleName;
}
name += " " + lastName;
现在,这有点冗长,但我发现它比以下更具可读性:
String name = firstName + (middleName == null ? "" : " " + middleName)
+ " " + lastName;
或:
String name = firstName;
name += (middleName == null ? "" : " " + middleName);
name += " " + lastName;
它似乎只是将过多的信息压缩到太小的空间中,而没有明确说明发生了什么。每当我看到使用三元运算符时,我总会找到一个似乎更容易阅读的替代方案......然后,这是一个非常主观的意见,所以如果你和你的同事发现三元非常易读,那就去吧。
嗯,它的语法很可怕。我发现函数ifs非常有用,并且通常使代码更具可读性。
我建议制作一个宏来让它更具可读性,但我确信有人会想出一个可怕的边缘情况(因为CPP总是如此)。
仅限于:
$ var =(simple <!> gt; test?simple_result_1:simple_result_2);
KISS。
我通常使用这样的东西:
before:
if(isheader)
drawtext(x,y,WHITE,string);
else
drawtext(x,y,BLUE,string);
after:
drawtext(x,y,isheader==true?WHITE:BLUE,string);
正如其他人指出的那样,它们适用于短暂的简单条件。我特别喜欢它们的默认设置(有点像javascript和python中的 || 和或用法),例如。
int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;
另一个常见用途是在C ++中初始化引用。由于必须在同一语句中声明和初始化引用,因此不能使用if语句。
SomeType& ref = pInput ? *pInput : somethingElse;
我对待三元运算符很像GOTO。它们有它们的位置,但它们通常应该避免使代码更容易理解。
我最近看到了三元运算符(好吧,有点)的变体,它们构成了标准的<!> quot;()? <!>:QUOT;变体似乎是一个清晰的典范:
var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]
或者,给出一个更切实的例子:
var Name = ['Jane', 'John'][Gender == 'm'];
请注意,这是Javascript,所以在其他语言中可能无法做到这一点(谢天谢地)。
对于简单的情况,我喜欢使用它。实际上,读取/编写例如函数或类似事件的参数要容易得多。另外为了避免新线路我喜欢与我的所有if / else保持一致。
在我的书中,这将是一个很大的NO-NO。
所以,恢复,对于单个if / else我将使用三元运算符。对于其他情况,常规的if / else if / else(或switch)
我喜欢Groovy关于三元运算符的特殊情况,称为Elvis运算符:?:
expr ?: default
此代码计算为expr,如果它不为null,则为默认值。从技术上讲,它不是一个真正的三元运算符,但它肯定与它相关并节省了大量的时间/打字。
对于简单的任务,例如根据条件分配不同的值,它们很棒。根据条件的不同,我会不会使用它们。
有很多答案说,取决于。我发现如果在快速扫描代码时看不到三元比较,那么就不应该使用它。
作为一个侧面问题,我可能还会注意到它的存在实际上有点像一个异常,因为在C中,比较测试是一种陈述。在Icon中,if
构造(与大多数Icon一样)实际上是一个表达式。所以你可以做以下事情:
x[if y > 5 then 5 else y] := "Y"
...我发现它比ternery比较运算符更具可读性。 : - )
最近讨论了将?:
运算符添加到Icon的可能性,但有几个人正确地指出,由于<=>的工作原理,完全没有必要。
这意味着如果你可以用C语言(或任何其他具有ternery算子的语言)来做,那么你实际上根本不需要ternery算子。
如果你和你的同事都明白他们做了什么并且他们不是在大量的小组中创建的,我认为他们会使代码变得更简单,更容易阅读,因为代码更少。
我认为三元运算符使代码更难理解的唯一一次是当你在一行中有超过3或4个时。大多数人都不记得他们是正确的优先权,当你有一堆它们时,它会使阅读代码成为一场噩梦。