C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Step 1: The condition inside the if is evaluated to a boolean value. The value equals 5 and thus the expression evaluates to true.
Step 2: The inner block, with Console.WriteLine, is reached. The string representation of true, "True" is printed.
C# program that uses if-statement
using System;
class Program
{
static void Main()
{
int value = 10 / 2;
// Step 1: test value against constant 5.
if (value == 5)
{
// Step 2: if expression evaluated to true, run this code.
Console.WriteLine(true);
}
}
}
Output
True
Tip: A test like (value == 10) evaluates to true or false. We can make explicit the comparison against true if we want.
C# program that shows comparison against true
using System;
class Program
{
static void Main()
{
int value = 10;
// Every expression in an if-statement must evaluate to true or false.
// ... A comparison that is true evaluates to true.
if (value == 10)
{
Console.WriteLine("TRUE");
}
if ((value == 10) == true)
{
Console.WriteLine("TRUE");
}
}
}
Output
TRUE
TRUE
So: We must test the more restrictive conditions first, or the less restrictive ones will match both cases.
Branches: In this program, the Test method uses several branching instructions expressed in high-level if-statements.
C# program that uses if, else
using System;
class Program
{
static void Main()
{
// Call method with embedded if-statement three times.
int result1 = Test(0);
int result2 = Test(50);
int result3 = Test(-1);
// Print results.
Console.WriteLine(result1);
Console.WriteLine(result2);
Console.WriteLine(result3);
}
static int Test(int value)
{
if (value == 0)
{
return -1;
}
else if (value <= 10)
{
return 0;
}
else if (value <= 100)
{
return 1;
}
else
{
return 2;
}
}
}
Output
-1
1
0
Method A: This version of the method uses a return statement at the end of an else-block.
Method B: This method has the same result as the method A, but omits the else-block.
Info: The 2 methods have equivalent performance and intermediate representations. This comes down to your style.
C# program that shows else constructs
using System;
class Program
{
static void Main()
{
Console.WriteLine(A(5)); // Call method A.
Console.WriteLine(B(4)); // Call method B.
}
static bool A(int y)
{
if (y >= 5)
{
return true;
}
else
{
return false;
}
}
static bool B(int y)
{
if (y >= 5)
{
return true;
}
return false;
}
}
Output
True
False
Tip: In this program, try changing the values of A and B to 1 and 2. With those values, the if-expressions both evaluate to false.
C# program that uses if, expressions
using System;
class Program
{
static void Main()
{
int a = 1;
int b = 3;
// Use negated expression.
if (!(a == 1 && b == 2))
{
Console.WriteLine(true);
}
// Use binary or version.
if (a != 1 || b != 2)
{
Console.WriteLine(true);
}
}
}
Output
True
True
Caution: This style is often a bad idea. You cannot add a second line to the body of one of these if-statements.
And: Visual Studio will now insert brackets automatically, so this style of code is not even faster to develop.
C# program that uses no brackets
using System;
class Program
{
static void Main()
{
int value = 1;
int size = 2;
if (value == 1)
if (size == 2)
Console.WriteLine("1, 2");
if (value == 0)
Console.WriteLine("0"); // Not reached.
else
Console.WriteLine("Not 0"); // Reached.
if (value == 2) Console.WriteLine("2"); // Not reached.
}
}
Output
1, 2
Not 0
Method1, Method2: These two methods are identical when compiled. No performance difference will exist.
Method3: This version inverts the order of the checks, so is faster when value > 100.
Note: Nesting ifs can help code clarity. If other statements need to be executed, nesting can also combine logic blocks.
C# program that uses nested ifs
using System;
class Program
{
static void Main()
{
Method1(50);
Method2(50);
Method3(50);
}
static void Method1(int value)
{
if (value >= 10)
{
if (value <= 100)
{
Console.WriteLine(true);
}
}
}
static void Method2(int value)
{
if (value >= 10 &&
value <= 100)
{
Console.WriteLine(true);
}
}
static void Method3(int value)
{
if (value <= 100 &&
value >= 10)
{
Console.WriteLine(true);
}
}
}
Output
True
True
True
C# program that causes error
class Program
{
static void Main()
{
int i = 100;
// This does not compile!
if (i = 200)
{
System.Console.WriteLine("Zebra");
}
}
}
Output
Error CS0029
Cannot implicitly convert type 'int' to 'bool'
Here: We have just a semicolon in the else block. This is valid, and the else clause would be considered empty.
But: This could be a typo, so the C# compiler helpfully warns us with the "possible mistaken empty statement" message.
Tip: Use an empty block with brackets if you wish to have an empty else-statement—no warning will be issued.
C# program that has possible mistaken empty statement
class Program
{
static void Main()
{
int bird = 2;
if (bird == 3)
{
}
else
;
}
}
Output
Warning CS0642
Possible mistaken empty statement
Example: We use the ternary operator in UseTernary(), and the if-else statements in UseIf.
Version 1: This code uses the ternary operator in UseTernary. If the argument is 5, it returns 10, otherwise it returns 20.
Version 2: This version use the if and else statements—the end result is the same as the ternary version.
Internals: The .NET Framework compiles the statements to the same branch statements in most cases (some slight differences can be present).
C# program that shows ternary statement
using System;
class Program
{
static void Main()
{
// Version 1: use ternary.
Console.WriteLine("TERNARY: " + UseTernary(5));
Console.WriteLine("TERNARY: " + UseTernary(100));
// Version 2: use if.
Console.WriteLine("IF: " + UseIf(5));
Console.WriteLine("IF: " + UseIf(100));
}
static int UseTernary(int argument)
{
return argument == 5 ?
10 :
20;
}
static int UseIf(int argument)
{
if (argument == 5)
{
return 10;
}
else
{
return 20;
}
}
}
Output
TERNARY: 10
TERNARY: 20
IF: 10
IF: 20
Tip: We can replace an if statement that tests against null, or a ternary statement, with a null coalescing expression.
C# program that uses null coalescing operator
using System;
class Program
{
static void Main()
{
// Use null coalescing instead of ternary or if-statements.
string value = null;
Console.WriteLine(value ?? "NO VALUE");
value = "bird";
Console.WriteLine(value ?? "NO VALUE");
}
}
Output
NO VALUE
bird
Version 1: This version of the code tests for the value 3 last in a series of if-statements.
Version 2: This version tests for the value 3 first in the if-statements. It uses the reorder-if optimization.
Result: Testing for the value that is most commonly seen first (in this program, 3) is faster. This can help with chained expressions also.
Tip: When we put the most common matching if-statement first, it becomes faster, but all others become slower. But overall, this is a win.
C# program that times if-reordering optimization
using System;
using System.Diagnostics;
class Program
{
const int _max = 1000000;
static void Main()
{
// Version 1: if-statements in non-optimized order.
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
Method1(100, 3);
}
s1.Stop();
// Version 2: most common match first (reordered ifs).
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
Method2(100, 3);
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
}
static int Method1(int max, int testValue)
{
// Test the argument in a loop.
int result = 0;
for (int i = 0; i < max; i++)
{
if (testValue == 1)
{
result++;
}
else if (testValue == 2)
{
result--;
}
else if (testValue == 3)
{
result += 2;
}
}
return result;
}
static int Method2(int max, int testValue)
{
// Test the argument in a loop, but with most common if first.
int result = 0;
for (int i = 0; i < max; i++)
{
if (testValue == 3)
{
result += 2;
}
else if (testValue == 1)
{
result++;
}
else if (testValue == 2)
{
result--;
}
}
return result;
}
}
Output
149.84 ns Tests 1, 2, 3 (value is 3)
101.98 ns Reordered, tests 3, 1, 2 (value is 3)
Version 1: This version of the code tests for 3 values and sets the result with if-else statements.
Version 2: This version uses a precomputed lookup table. It generates the same results as version 1.
Result: The mapping from test value to result value is the same in each version of the code. But the lookup table consistently is faster.
Tip: This optimization is easiest when each test value has a single result value. A dictionary can also be used as lookup table.
C# program that times lookup table optimization
using System;
using System.Diagnostics;
class Program
{
const int _max = 10000000;
static void Main()
{
int[] lookup = new int[] { 10, 50, 7 };
// Version 1: use if, else statements to get a single int result.
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
int test = i % 3;
int result = 0;
if (test == 0)
{
result = 10;
}
else if (test == 1)
{
result = 50;
}
else if (test == 2)
{
result = 7;
}
if (result == 0)
{
break;
}
}
s1.Stop();
// Version 2: use lookup table instead of if to get a single int result.
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
int test = i % 3;
int result = lookup[test];
if (result == 0)
{
break;
}
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
}
}
Output
2.92 ns if/else if/else if chain
2.47 ns lookup[test]
Switch: Sometimes a switch statement is faster than an if-statement. But this is a complex issue.
If vs. SwitchSwitchDictionary: A Dictionary can be used as a lookup table. This transforms complex if-statements into a single lookup.
DictionaryVirtual dispatch: Use the type system to add behavior to objects. Place objects in a Dictionary and call their virtual methods.
VirtualHowever: These blocks have no meaning to the execution engine. They are instead translated into single instructions in IL.
And: The IL is flat. It is without scope. If-statements are translated to branch instructions.
IL: bneAnd: If 2 paths are possible, it is often better to put the common one in the if, and the uncommon one in the else.
Important: The more important (common) paths should come first. So we minimize the number of instructions.
Quote: Write your code so that the normal path through the code is clear. Make sure that the rare cases don't obscure the normal path of execution. This is important for both readability and performance (Code Complete).