三元か三元でないか?
私は個人的に三項演算子の擁護者です:()? :;私はそれがその場所を持っていることを知っていますが、私はそれを使用することに完全に反対し、あまりにも頻繁にそれを使用する多くのプログラマに出くわしました。
それに対するあなたの気持ちは何ですか?それを使用してどのような興味深いコードを見ましたか?
単純な式のみに使用します:
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;
}
編集-
私は、三項演算子がすべてを他の演算子よりも複雑さを減らし、よりきれいにすると主張します。
連鎖-私は大丈夫-入れ子になった、それほどではない。
私はそれらを値を持つif文であるC/Cでより多く使用する傾向があるので、不必要な繰り返しや変数を削減します:
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
(確かに、この単純なことのために、とにかく三項演算子を使用するかもしれません)。
Ternary ?:
演算子は、手続き上のif
コンストラクトと機能的に同等です。したがって、ネストされた?:
式を使用していない限り、任意の操作の機能的表現の引数/に対する引数がここに適用されます。しかし、3項演算をネストすると、まったく紛らわしいコードになる可能性があります(読者のための練習:ネストされた3項条件を処理するパーサーを作成してみてください。
ただし、?:
演算子を控えめに使用すると、実際には簡単であるコードが他の方法よりも読み取れる場合があります。例えば:
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)
)
単純な割り当て操作のために簡潔でエレガントだからです。
非常に多くの意見の質問のように、答えは必然的です:it depend
次のようなもの:
return x ? "Yes" : "No";
私はそれがmuchよりも簡潔である(そして私が解析するのが速い)と思う:
if (x) {
return "Yes";
} else {
return "No";
}
条件式が複雑な場合、3項演算は適切な選択ではありません。何かのようなもの:
x && y && z >= 10 && s.Length == 0 || !foo
三項演算子の良い候補ではありません。
余談ですが、Cプログラマーの場合、GCCには実際には 拡張子 があり、次のように三項のif-true部分を除外できます。
/* 'y' is a char * */
const char *x = y ? : "Not set";
x
がy
ではない場合、y
をNULL
に設定します。いい物。
私の考えでは、式が必要な場合にのみ三項演算子を使用する意味があります。
他のケースでは、三項演算子が明確さを低下させるようです。
循環的複雑度 の尺度により、if
ステートメントまたは三項演算子の使用は同等です。そのため、答えはnoであり、複雑さは以前とまったく同じになります。
読みやすさ、保守性、およびDRY(Don't-Repeat-Yourself))などの他の手段により、どちらの選択肢が他の選択肢よりも優れていることがわかります。
コンストラクターでの作業が制限されている場所(新しい.NET 3.5 LINQ to XMLコンストラクトなど)で頻繁に使用して、オプションのパラメーターがnullの場合の既定値を定義します。
考案された例:
var e = new XElement("Something",
param == null ? new XElement("Value", "Default")
: new XElement("Value", param.ToString())
);
または(アスタライトに感謝)
var e = new XElement("Something",
new XElement("Value",
param == null ? "Default"
: param.ToString()
)
);
三項演算子を使用するかどうかに関係なく、コードが読み取り可能であることを確認することが重要です。どの構造も読み取り不能にすることができます。
コードを非常に読みにくくしない限り、可能な限り三項演算子を使用しますが、それは通常、コードが少しリファクタリングを使用できることを示しています。
一部の人々が三項演算子が「隠された」機能であるか、やや神秘的であると考えるのはいつも私を困惑させます。これは、Cでプログラミングを開始したときに学んだ最初のことの1つであり、読みやすさを低下させるとは思わない。それは言語の自然な部分です。
(今日のハック)
#define IF(x) x ?
#define ELSE :
その後、式としてif-then-elseを実行できます。
int b = IF(condition1) res1
ELSE IF(condition2) res2
ELSE IF(conditions3) res3
ELSE res4;
私はjmulderに同意します:if
の代わりに使用すべきではありませんが、return式または式内にその場所があります:
echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;
前者は単なる例であり、複数形のより良い国際化サポートを使用する必要があります!
単純な条件付き代入に三項演算子を使用している場合、それは問題ないと思います。割り当てを行わずにプログラムフローを制御する(ab)のを見てきましたが、これは避けるべきだと思います。これらの場合はifステートメントを使用します。
私はそれらが好きです。理由はわかりませんが、3進表現を使うととてもクールに感じます。
私はそのような獣を見てきました(それは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");
必要なときに三項演算子を使用する必要があると思います。これは明らかに非常に主観的な選択ですが、単純な式(特に戻り式として)は完全なテストよりもはるかに明確であることがわかります。 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の論理演算子のプロパティを使用します。それらは遅延し、最終状態と等しい場合に計算された最後の値を返します。
三項演算子を使用することはほとんどありません。使用するたびに、後でそれを維持しようとするときよりもずっと多くのことを考えさせるからです。
冗長性を避けるのが好きですが、それがコードをより簡単に理解できるようになったら、冗長性に取り組みます。
考慮してください:
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;
何が起こっているのかを明確にせずに、あまりにも多くの情報を小さすぎるスペースに圧縮しているようです。三項演算子が使用されるのを見るたびに、ずっと読みやすいと思われる代替案を見つけました...それもまた、非常に主観的な意見です。
デバッグコードで演算子を使用してエラー値を出力するのが好きなので、常に検索する必要はありません。通常、これは、開発が完了したら残っていないデバッグプリントに対して行います。
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");
}
他の人が指摘しているように、彼らは短い単純な条件にはいいです。特にデフォルト(JavascriptとPythonでやorのようなもの)が好きです。
int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;
別の一般的な使用法は、C++で参照を初期化することです。参照は同じステートメントで宣言および初期化する必要があるため、ifステートメントは使用できません。
SomeType& ref = pInput ? *pInput : somethingElse;
の時だけ:
$ var =(simple> test?simple_result_1:simple_result_2);
キッス。
まあ、それの構文は恐ろしいです。機能的ifは非常に便利で、コードを読みやすくすることがよくあります。
より読みやすくするためにマクロを作成することをお勧めしますが、だれかが恐ろしいEdgeケースを思い付くことができると確信しています(常にCPPにあるように)。
私は通常、次のようなもので使用します:
before:
if(isheader)
drawtext(x,y,WHITE,string);
else
drawtext(x,y,BLUE,string);
after:
drawtext(x,y,isheader==true?WHITE:BLUE,string);
条件に応じて異なる値を割り当てるような単純なタスクの場合、それらは素晴らしいです。条件thoに応じてより長い表現がある場合、それらを使用しません。
あなたとあなたの同僚が彼らが何をしているのかを理解し、彼らが大規模なグループで作成されていない場合、単純にコードが少ないため、コードが複雑で読みにくくなります。
三項演算子がコードを理解しにくくすると思うのは、1行に3つまたは4つ以上ある場合だけです。ほとんどの人は、それらが正しいベースの優先順位であることを覚えておらず、それらのスタックがある場合、コードを読むことは悪夢になります。
私は最近、標準の "()?:"バリアントを明快さの模範とする3項演算子(まあ、ある種)のバリエーションを見ました。
var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]
または、より具体的な例を挙げます:
var Name = ['Jane', 'John'][Gender == 'm'];
念のため、これはJavascriptなので、そのようなことは他の言語では不可能な場合があります(ありがたいことに)。
非常に多くの回答が、それは依存しますと言っています。コードのクイックスキャンで3項比較が表示されない場合は、使用しないでください。
副次的な問題として、Cでの比較テストはステートメントであるという事実により、その存在自体が実際には少し異常であることに注意するかもしれません。 Iconでは、if
コンストラクト(ほとんどのIconと同様)は実際には式です。そのため、次のようなことができます。
x[if y > 5 then 5 else y] := "Y"
... ternery比較演算子よりもはるかに読みやすいと思います。 :-)
最近?:
演算子をIconに追加する可能性について議論がありましたが、いくつかの人々はif
が機能するためにまったく必要がないことを正しく指摘しました。
つまり、C(またはternery演算子を持つ他の言語)でそれができれば、実際にはternery演算子はまったく必要ないということです。
単純なifの場合、私はそれを使うのが好きです。実際、関数やそのようなもののパラメーターとして、たとえば読み取り/コード化する方がはるかに簡単です。また、新しい行を避けるために、すべてのif/elseを保持します。
それをネセットすることは、私の本では大したことないでしょう。
したがって、再開すると、単一のif/elseに対して、三項演算子を使用します。その他の場合は、通常のif/else if/else(またはスイッチ)
エルビス演算子と呼ばれるGroovyの三項演算子の特殊なケースが好きです:?:
expr ?: default
このコードは、nullでない場合はexprと評価され、nullでない場合はデフォルトに評価されます。技術的には実際には三項演算子ではありませんが、間違いなくそれに関連しており、多くの時間/タイピングを節約します。
私は三項演算子をGOTOのように扱います。それらには場所がありますが、コードを理解しやすくするために通常避けるべきものです。
三項演算子は伝承します。適切にフォーマットすれば、それらは複雑ではありません。 @paxdiabloからうるう年の例を取り上げます。
$isLeapYear =
(($year % 400) == 0)
? 1
: ((($year % 100) == 0)
? 0
: ((($year % 4) == 0)
? 1
: 0));
これは、このフォーマットでより簡潔に記述し、はるかに読みやすくすることができます。
//--------------test expression-----result
$isLeapYear = (($year % 400) == 0) ? 1 :
((($year % 100) == 0)? 0 :
((($year % 4) == 0) ? 1 :
0));//default result
それを使用して:
- object(array)プロパティへのアクセス:
var status = statuses[error == null ? 'working' : 'stopped'];
- return文:
function getFullName(){ return this.isMale() ? "Mr. " : "Ms. "+ this.name; }
変数を初期化する:
var formMethod = DEBUG_FLAG == true ? "GET" : "POST";
- 引数の検証:
function(object){ var prop1 = typeof object.property == 'undefined' ? "default prop" : object.property; //... }
コード例はjavascriptにあります
三項演算子を使用する必要があるかどうかを判断するために最近作成した経験則は次のとおりです。
- コードで2つの異なる値を選択している場合は、3項演算子を使用してください。
- コードで2つの異なるコードパスを選択する場合は、ifステートメントを使用します。
そして、コードの読者に親切にしてください。三項演算子をネストしている場合は、コードをフォーマットして、ネストを明確にします。
論理式のconditionsの数が読みにくくなると思います。これはifステートメントにも当てはまり、3項演算子にも当てはまります。完全な世界では、one他とは対照的にブランチを取る理由を要約できるはずです。説明が「この状態のクラスターが発生した場合のみ」である場合、実際には「ビジネスルール」に近い可能性があります。
ただし、realの世界では、理想的なケースに従うためだけに、状態を1つの表現可能な状態にフォールディングする中間ステップを追加しません。複数の状態について推論を行い、それらの処理方法を決定する必要があります。
I like 3項if文でanythingを実行できるためです。
if( object.testSomeCondition()) {
System.exec( "format c:" );
}
else {
a++;
}
一方:
a += ( object.testSomeCondition() ? 0 : 1 );
clearにすると、目標はa
の値を見つけることです。もちろん、それに沿って、おそらくshould n'tは合理的な副作用以上のものです。
簡単な質問に答えられるように、上流で条件を修正する時間があるかどうかを判断した後、長い条件または複雑な条件に
if
を使用します。しかし、ifを使用するとき、私はstillを実行しようとしますparallel異なる条件の下で処理します。if ( user.hasRepeatedlyPressedOKWithoutAnswer() && me.gettingTowardMyLunchtime( time ) ) { ... }
また、私の目標はnear-single-stream processingです。ですから、私はよくnotを試して
else
を実行しますが、if
は単に共通パスから外れただけです。多くのシングルストリーム処理を行う場合、バグがコード内に隠れて、ジャンプして問題を引き起こす1つの条件を待機することははるかに困難です。上記で述べたように、3値を使用してone thingを設定する場合、または値を設定するためにテストしたいケースが少数ある場合は、のような読みやすさ三元の。
1つの注意事項があります--- NO COMPLEX true CLAUSES
a = b == c ? ( c == d ? ( c == e ? f : g ) : h ) : i;
もちろん、これは次のように分解できます。
a = b != c ? i
: c != d ? h
: c == e ? f
: g
;
そして、それは(compressed)真理値表のように見えます。
より重要読みやすさの要因があることに注意してください。そのうちの1つはブロック長で、もう1つはインデントレベルです。単純なことを3進法で実行しても、インデントのレベルがさらに高くなることはありません。
いいえ。読みにくいです。 If/Elseは読みやすくなっています。
これは私の意見。あなたのマイレージは異なる場合があります。
それは大好きです。使用する場合、if-then-elseのように記述します:条件、真のアクション、および偽のアクションごとに1行。そうすれば、簡単にネストできます。
例:
x =(a == b ?(sqrt(a)-2) :(a * a + b * b) ); x =(a == b ?(sqrt(a)-2) :(a * a + b * b) ) ; x =(a == b ?(c> d ?(sqrt(a)-2) :(c + cos(d) ) ) :(a * a + b * b) );
私には、これはかなり読みやすいです。また、サブケースを簡単に追加したり、既存のケースを変更したりできます。
少なくとも型推論をサポートするDのような言語では、三項演算子の使用について誰も言及していないように思われる理由の1つは、驚くほど複雑なテンプレート型に対して型推論を機能させることです。
auto myVariable = fun();
// typeof(myVariable) == Foo!(Bar, Baz, Waldo!(Stuff, OtherStuff)).
// Now I want to declare a variable and assign a value depending on some
// conditional to it.
auto myOtherVariable = (someCondition) ? fun() : gun();
// If I didn't use the ternary I'd have to do:
Foo!(Bar, Baz, Waldo!(Stuff, OtherStuff)) myLastVariable; // Ugly.
if(someCondition) {
myLastVariable = fun();
} else {
myLastVariable = gun():
}
いいえ、三項演算子しない複雑さが増します。残念ながら、一部の開発者は命令型プログラミングスタイルを重視しているため、他の何かを拒否します(または学習しません)。私はそれを信じていません、例えば:
int c = a < b ? a : b;
同等のものより「より複雑」(ただし、より詳細):
int c;
if (a < b) {
c = a;
} else {
c = b;
}
またはさらに厄介な(私が見た):
int c = a;
if (!a < b) {
c = b;
}
そうは言っても、ケースバイケースで選択肢を注意深く見てください。適切な教育を受けた開発者を想定して、コードの意図を最も簡潔に表現しているのはどれかを尋ね、そのコードを使用します。
以前は「三項演算子を使用して行を読めなくする」キャンプにいましたが、ここ数年、適度に使用することで彼らを好きになりました。チームの全員が何が起こっているかを理解していれば、単一行の三項演算子で読みやすくなります。これは、中かっこのために多くの中かっこのオーバーヘッドなしで何かを行う簡潔な方法です。
気に入らない2つのケース:120列のマークを超えすぎている場合、または他の三項演算子に埋め込まれている場合。 3項演算子で何をしているかをすばやく、簡単に、読みやすく表現できない場合。次に、同等のif/elseを使用します。
場合によります :)
Nullの可能性のある参照を処理する場合に便利です(btw:Javaは、nullの可能性のある2つの文字列を簡単に比較する方法が本当に必要です)。
問題は、1つの式に多くの3項演算子をネストしているときに始まります。
いいえ(誤用されていない限り)。式がより大きな式の一部である場合、三項演算子の使用はより明確になることがよくあります。
三項演算子は、コンマ区切りリストを簡潔に作成するのに非常に便利です。 Javaの例:
int[] iArr = {1,2,3};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iArr.length; i++) {
sb.append(i == 0 ? iArr[i] : "," + iArr[i]);
}
System.out.println(sb.toString());
生成: "1,2,3"
そうしないと、最後のコンマの特殊な大文字小文字が煩わしくなります。
コードの行数を削減しようとしている場合、またはコードをリファクタリングしている場合は、そのままにしてください。
式を理解するために余分な0.1ミリ秒を必要とする次のプログラマが気になる場合は、とにかくそれを続けてください。
コードを小さくしても、解析が簡単になるとは限りません。は言語によって異なります。 PHPたとえば、PHPの字句解析器はコードを最初に改行で始まり、次に空白で分割するため、空白と改行が推奨されます。使用される空白が少なくなります。
悪い:
($var)?1:0;
良い:
($var) ? 1 : 0;
大きな問題ではないように思えますが、PHPの字句解析コードでは、空白が不可欠です。さらに、この方法でも少し読みやすくなります。
文字列someSay = bCanReadThis? "いいえはい";
ロジックが簡単な状況でコード行を回避するために、3項を使用および推奨します。
int i;
if( piVal ) {
i = *piVal;
} else {
i = *piDefVal;
}
上記の場合、ノイズが少ないため、3成分を選択します。
int i = ( piVal ) ? *piVal : *piDefVal;
同様に、条件付き戻り値も適切な候補です。
return ( piVal ) ? *piVal : *piDefVal;
コンパクトさは読みやすさを改善し、ひいてはコード品質の改善に役立つと思います。
しかし、読みやすさは常にコードの対象者に依存します。
読者は精神的な努力なしにa ? b : c
パターンを理解できなければなりません。これを推測できない場合は、長いバージョンを使用してください。
私はそれが本当に使用されているコンテキストに依存すると思います。
このようなものは、効果的ではありますが、実際には混乱を招く方法です。
__CRT_INLINE int __cdecl getchar (void)
{
return (--stdin->_cnt >= 0)
? (int) (unsigned char) *stdin->_ptr++
: _filbuf (stdin);
}
ただし、これ:
c = a > b ? a : b;
完全に合理的です。
個人的には、過度に冗長なIFステートメントを削減するときに使用すべきだと思います。問題は、人々が彼らを石化するか、IFステートメントの代わりにほとんど排他的に使用されることを好みます。
誰もが三項演算子なしで難読化されたコードコンテストに勝つでしょうか?!
必要に応じて個人的に使用していますが、ネストすることはないと思います。非常に便利ですが、コードを読みにくくし、他の操作(Groovyのnullチェックなど)の他のいくつかの言語で使用されているという点で、いくつかの欠点があります。
ここの多くのポスターの感情に同意します。三項演算子は、正しく使用され、あいまいさを引き起こさない限り、完全に有効です(公平に言えば、任意の演算子/構成について言えます)。
私はコードが何をしているのかを明確にするために、組み込みコードで三項演算子をよく使用します。次の(わかりやすくするために簡略化された)コードサンプルを使用します。
スニペット1:
int direction = read_or_write(io_command);
// Send an I/O
io_command.size = (direction==WRITE) ? (32 * 1024) : (128 * 1024);
io_command.data = &buffer;
dispatch_request(io_command);
スニペット2:
int direction = read_or_write(io_command);
// Send an I/O
if (direction == WRITE) {
io_command.size = (32 * 1024);
io_command.data = &buffer;
dispatch_request(io_command);
} else {
io_command.size = (128 * 1024);
io_command.data = &buffer;
dispatch_request(io_command);
}
ここでは、入力要求または出力要求をディスパッチしています。プロセスは、要求が読み取りでも書き込みでも同じです。デフォルトのI/Oサイズのみが変更されます。最初のサンプルでは、三項演算子を使用して、プロシージャが同じであり、size
フィールドがI/O方向に応じて異なる値を取得することを明確にします。 2番目の例では、2つのケースのアルゴリズムが同じであることはすぐにはわかりません(特に、コードが3行よりはるかに長くなるため)。 2番目の例は、共通コードの同期を保つのがより困難です。ここで、三項演算子は、コードの大部分が並列であるという性質をより適切に表現しています。
三項演算子には別の利点があります(通常は組み込みソフトウェアの問題にすぎません)。一部のコンパイラは、コードが特定の深さを超えて「ネスト」されていない場合にのみ特定の最適化を実行できます(関数内では、if、loop、またはswitchステートメントを入力するたびにネストの深さを1ずつ増やし、あなたはそれを残します)。場合によっては、三項演算子を使用すると、条件内に必要なコードの量を最小化でき(コンパイラーが条件を最適化できるポイントまで)、コードのネストの深さを減らすことができます。場合によっては、上記の例のように三項演算子を使用して一部のロジックを再構築し、コンパイラが追加の最適化手順を実行できるように関数のネストの深さを十分に減らすことができました。確かにこれはかなり狭いユースケースですが、とにかく言及する価値があると思いました。
少量では、行数を減らしてコードを読みやすくすることができます。特に、結果が計算の結果に基づいて文字列を「はい」または「いいえ」に設定するようなものである場合。
例:
char* c = NULL;
if(x) {
c = "true";
}else {
c = "false";
}
と比べて:
char* c = x ? "Yes" : "No";
そのような単純なテストで発生する可能性がある唯一のバグは、誤った値を割り当てることですが、通常、条件は単純であるため、プログラマが間違っている可能性は低くなります。プログラムに間違った出力を出力させることは世界の終わりではなく、コードレビュー、ベンチテスト、および実稼働テストのすべての段階でキャッチする必要があります。
私は自分の主張に反論します。今では、コードカバレッジメトリックを使用して、テストケースがどれだけ優れているかを知るのを支援することはより困難です。最初の例では、両方の割り当てラインでカバレッジをテストできます。カバーされていない場合、テストはすべての可能なコードフローを実行していません。
2番目の例では、Xの値に関係なく行が実行されていると表示されるため、代替パス(カバレッジツールの機能に応じてYMMV)をテストしたかどうかを確認することはできません。
これは、テストの複雑さが増すにつれて重要になります。
あなたの三項演算子が画面全体の幅を取ることになった場合、私はそれを使用しません。 1つの単純な条件をチェックし、単一の値を返すだけです。
int x = something == somethingElse ? 0 : -1;
実稼働環境では、実際にこのような厄介なコードがいくつかあります...良くありません:
int x = something == (someValue == someOtherVal ? string.Empty : "Blah blah") ? (a == b ? 1 : 2 ): (c == d ? 3 : 4);
状況によってはオペレーターが好きですが、一部の人々はそれを使いすぎる傾向があり、コードが読みにくくなる可能性があると思います。
私は最近、私が修正しようとしているいくつかのオープンソースコードで、この行につまずいた。
where
(active == null ? true :
((bool)active ? p.active : !p.active)) &&...
の代わりに
where ( active == null || p.active == active) &&...
この場合、3項使用によりLINQステートメントに余分なオーバーヘッドが追加されるのではないかと思います。
興味深い逸話:インライン化の目的では、オプティマイザーの重みの三項演算子は、同等のifよりも「重い」と見なされています。 Microsoftコンパイラでこれに気づきましたが、もっと広範囲に及ぶ可能性があります。
このような特定の関数では、インラインになります:
int getSomething()
{
return m_t ? m_t->v : 0;
}
しかし、これはしません:
int getSomething()
{
if( m_t )
return m_t->v;
return 0;
}