Benefits of using the conditional ?: (ternary) operator
I would basically recommend using it only when the resulting statement is extremely short and represents a significant increase in conciseness over the if/else equivalent without sacrificing readability.
Good example:
int result = Check() ? 1 : 0;
Bad example:
int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0;
Benefits of ternary operator vs. if statement
Performance
The ternary operator shouldn't differ in performance from a well-written equivalent if
/else
statement... they may well resolve to the same representation in the Abstract Syntax Tree, undergo the same optimisations etc..
Things you can only do with ? :
If you're initialising a constant or reference, or working out which value to use inside a member initialisation list, then if
/else
statements can't be used but ?
:
can be:
const int x = f() ? 10 : 2;
X::X() : n_(n > 0 ? 2 * n : 0) { }
Factoring for concise code
Keys reasons to use ?
:
include localisation, and avoiding redundantly repeating other parts of the same statements/function-calls, for example:
if (condition)
return x;
else
return y;
...is only preferable to...
return condition ? x : y;
...on readability grounds if dealing with very inexperienced programmers, or some of the terms are complicated enough that the ?
:
structure gets lost in the noise. In more complex cases like:
fn(condition1 ? t1 : f1, condition2 ? t2 : f2, condition3 ? t3 : f3);
An equivalent if
/else
:
if (condition1)
if (condition2)
if (condition3)
fn(t1, t2, t3);
else
fn(t1, t2, f3);
else if (condition3)
fn(t1, f2, t3);
else
fn(t1, f2, f3);
else
if (condition2)
...etc...
That's a lot of extra function calls that the compiler may or may not optimise away.
Further, ?
allows you to select an object, then use a member thereof:
(f() ? a : b).fn(g() ? c : d).field_name);
The equivalent if
/else
would be:
if (f())
if (g())
x.fn(c.field_name);
else
x.fn(d.field_name);
else
if (g())
y.fn(c.field_name);
else
y.fn(d.field_name);
Can't named temporaries improve the if/else monstrosity above?
If the expressions t1
, f1
, t2
etc. are too verbose to type repeatedly, creating named temporaries may help, but then:
To get performance matching
?
:
you may need to usestd::move
, except when the same temporary is passed to two&&
parameters in the function called: then you must avoid it. That's more complex and error-prone.c
?
x:
y evaluates c then either but not both of x and y, which makes it safe to say test a pointer isn'tnullptr
before using it, while providing some fallback value/behaviour. The code only gets the side effects of whichever of x and y is actually selected. With named temporaries, you may needif
/else
around or?
:
inside their initialisation to prevent unwanted code executing, or code executing more often than desired.
Functional difference: unifying result type
Consider:
void is(int) { std::cout << "int\n"; }
void is(double) { std::cout << "double\n"; }
void f(bool expr)
{
is(expr ? 1 : 2.0);
if (expr)
is(1);
else
is(2.0);
}
In the conditional operator version above, 1
undergoes a Standard Conversion to double
so that the type matched 2.0
, meaning the is(double)
overload is called even for the true
/1
situation. The if
/else
statement doesn't trigger this conversion: the true
/1
branch calls is(int)
.
You can't use expressions with an overall type of void
in a conditional operator either, whereas they're valid in statements under an if
/else
.
Emphasis: value-selection before/after action needing values
There's a different emphasis:
An if
/else
statement emphasises the branching first and what's to be done is secondary, while a ternary operator emphasises what's to be done over the selection of the values to do it with.
In different situations, either may better reflect the programmer's "natural" perspective on the code and make it easier to understand, verify and maintain. You may find yourself selecting one over the other based on the order in which you consider these factors when writing the code - if you've launched into "doing something" then find you might use one of a couple (or few) values to do it with, ?
:
is the least disruptive way to express that and continue your coding "flow".
advantage of ternary operator over if else?
If you look at the disassembly of both approaches, they're generally the same on any modern compiler I know of. The ternary operator is just a compact form of writing the same thing.
Here's an example using gcc 4.2.1 on Mac OS X:
With if/else:
int x = 1;
int y = 2;
int z;
if (x < y)
{
z = 3;
}
else
{
z = 4;
}
With the ternary operator:
int x = 1;
int y = 2;
int z = (x < y) ? 3 : 4;
If you run gcc -S test.c on both of these, you get this assembly for the if/else version:
movl $1, -16(%rbp)
movl $2, -20(%rbp)
movl -16(%rbp), %eax
movl -20(%rbp), %ecx
cmpl %ecx, %eax
jge LBB1_2
movl $3, -12(%rbp)
jmp LBB1_3
LBB1_2:
movl $4, -12(%rbp)
and this for the ternary operator version:
movl $1, -12(%rbp)
movl $2, -16(%rbp)
movl -12(%rbp), %eax
movl -16(%rbp), %ecx
cmpl %ecx, %eax
jge LBB1_2
movl $3, -20(%rbp)
jmp LBB1_3
LBB1_2:
movl $4, -20(%rbp)
The register offsets are different, but functionally, the code does the same thing. It adds two literals to two different registers, then compares and jumps based on the result of the comparison.
C# - Are there any advantages or benefits to using ternary operators?
The ternary operator is more concise: less typing and quicker to read. The compiled IL code or the JITted native code are likely to be identical. If not, any performance differences are almost certain to be virtually unmeasurably small. Therefore, source code quality is the only real consideration in making the decision.
"Tertiary" means "third in importance"; "ternary" means "having three parts."
I personally prefer the term "conditional operator" because it's entirely possible that someone will invent another ternary operator in the future. Imagine if we had to call +
the "first binary operator" and -
the "second binary operator"!
Why would you choose to use the ternary operator (?:) over a traditional if..else block?
As you say, is a compressed if-then-else, so it must be compiled to the same instructions with regards of the comparisons.
The real difference is that it selects a final result. Really, just syntactic sugar that improves readability.
Compare:
int val = (foobar == true) ? 500 : 1000 ;
vs:
int val = 0;
if (foobar == true)
{
val = 500;
} else {
val = 1000;
}
It can be argued that it is just a matter of style, thus subjective. But, the legibility becomes even greater when you have a more complex decision tree, such as:
int val = (flag01 == true) ?
(flag02 == true ) ? 100 : 200 :
(flag03 == true ) ? 300 : 400 ;
You can chain together many decisions in one place instead of writing a bunch of nested if-then-else clauses:
int val = 0;
if (flag01 == true)
{
if (flag02 == true)
{
val = 100;
} else {
val = 200;
}
} else {
if (flag03 == true)
{
val = 300;
} else {
val = 400;
}
}
This is somewhat following a code pattern called method chaining.
To ternary or not to ternary?
Use it for simple expressions only:
int a = (b > 10) ? c : d;
Don't chain or nest ternary operators as it hard to read and confusing:
int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;
Moreover, when using ternary operator, consider formatting the code in a way that improve readability:
int a = (b > 10) ? some_value
: another_value;
Ternary ? operator vs the conventional If-else operator in c#
I ran 100 million Ternary Operators and 100 million If-Else statements and recorded the performance of each. Here is the code:
Stopwatch s = new Stopwatch();
// System.Diagnostics Stopwatch
int test = 0;
s.Start();
for(int a = 0; a < 100000000; a++)
test = a % 50 == 0 ? 1 : 2;
s.Stop();
s.Restart();
for(int b = 0; b < 100000000; b++)
{
if(b % 50 == 0)
test = 1;
else
test = 2;
}
s.Stop();
Here is the results (ran on an Intel Atom 1.66ghz with 1gb ram and I know, it sucks):
Ternary Operator: 5986 milliseconds or 0.00000005986 seconds per each operator.
If-Else: 5667 milliseconds or 0.00000005667 seconds per each statement.
Don't forget that I ran 100 million of them, and I don't think 0.00000000319 seconds difference between the two matters that much.
Full if/else statement vs. Conditional Operator
Don't focus on writing less code... focus on the code you end up with being more readable.
Sometimes an if
statement will be more readable. Sometimes the conditional operator will be more readable. I like the conditional operator in cases where it makes sense, in terms of different ways of calculating one logical value (e.g. a discount, based on the age of a customer). I don't like using it in convoluted ways though - there's nothing wrong with using a full if/else where it makes sense.
It's worth remembering the null-coalescing operator too... so instead of:
string shipTo = customer.ShippingAddress != null
? customer.ShippingAddress : customer.BillingAddress;
you can use
string shipTo = customer.ShippingAddress ?? customer.BillingAddress;
Again, it's only useful in certain situations - but in those cases it's really handy.
Related Topics
Parsing CSV Files in C#, With Header
Split List into Sublists With Linq
C# Difference Between == and Equals()
How to Make a Textbox That Only Accepts Numbers
An Async/Await Example That Causes a Deadlock
How to Do Impersonation in .Net
Asynchronously Wait For Task≪T≫ to Complete With Timeout
Type.Gettype("Namespace.A.B.Classname") Returns Null
In C#, Why Can't a List≪String≫ Object Be Stored in a List≪Object≫ Variable
What Are Your Favorite Extension Methods For C# (Codeplex.Com/Extensionoverflow)
How to Save a Stream to a File in C#
Difference Between New and Override