if
-else
Statements
Run the example program, clothes/clothes.cs. Try it at least twice, with inputs 50 and then 80. As you can see, you get different results, depending on the input. The main code of clothes/clothes.cs is:
1double temperature = UIF.PromptDouble("What is the temperature? ");
2if (temperature > 70) {
3 Console.WriteLine("Wear shorts.");
4}
5else {
6 Console.WriteLine("Wear long pants.");
7}
8Console.WriteLine("Get some exercise outside.");
The lines labeled 2-7 are an if
-else
statement. Again it is
close to English, though you might say “otherwise” instead of
“else” (but else is shorter!). There are two indented statements
in braces:
One, like in the simple if
statement, comes right after the
if
condition and is executed when the condition is true.
In the if
-else
form this is followed by an
else
(lined up under the if
by convention),
followed by another indented statement enclosed in braces that is only
executed when the original condition is false. In an if
-else
statement exactly one of two possible parts in braces is executed.
A final line is also shown that is not indented, about getting exercise.
The if
and else
clauses each
only embed a single (possibly compound) statement
as option, so the last statement is not part of the if
-else
statement. It is beyond the if
-else
statement; it is
just a part of the normal sequential
flow of statements. We repeat:
Note
Inside an if
-else
there is a
choice made of which clause to execute and which clause to skip,
but the whole if
-else
construction is a single
larger statement, which exists in the normal sequential flow
of execution.
The compiler does not require the indentation of the if-true-statement and the if-false-statement, but it is a standard style convention.
The general C# if
-else
syntax is
if (
condition ) {
}
else {
}
The statements chosen based on the condition
can be any kind of statement. This is the suggested form, but
as with the plain if
statement, the if-true compound statement or
the if-false compound statement can be replace by a single statement
without braces, except in one otherwise ambiguous situation later,
Match Wrong if With else.
Scope With Compound Statements
The section Local Scope referred to function bodies, which happen to be enclosed in braces, making the function body a compound statement. In fact variables declared inside any compound statement have their scope restricted to inside that compound statement.
As a result the following code makes no sense:
static int BadBlockScope(int x)
{
if ( x < 100) {
int val = x + 2;
}
else {
int val = x - 2:
}
return val;
}
The if
-else
statement is legal, but useless,
because whichever compound statement gets executed,
val
ceases being defined after the
closing brace of its compound statement,
so the val
in the return statement has
not been declared or given a value. The code
would generate a compiler error.
If we want val
be used inside the braces and
to make sense past the end of the compound statement,
it cannot be declared inside the braces. Instead it must be
declared before the compound statements that are parts of the
if
-else
statement. A local variable in a function declared before a nested compound
statement is still visible (in scope) inside that compound statement.
The following would work:
static int OkScope(int x)
{
int val;
if (x < 100) {
val = x + 2;
}
else {
val = x - 2;
}
return val;
}
There is even more subtlety here than meets the eye:
An if
-else
statement can generally be rewritten as two simple
if statements (though it is less efficient and less clear).
The two if
statements would use opposite conditions, as in this variation:
1static int OkScope2(int x)
2{
3 // without the = 0: Unassigned local variable error
4 int val = 0;
5 if (x < 100) {
6 val = x + 2;
7 }
8 if (x >= 100) {
9 val = x - 2;
10 }
11 return val;
12}
Note that in this variation we added an
initialization for val
to be 0, though the
value of the initialization is never used: val
is
guaranteed to be assigned a value in one of the if
statements
before its value is used in the return statement.
Open Xamarin Studio with the examples solution, and open
ok_if_scope/ok_if_scope.cs in the edit window.
The last function, OkScope2
,
is the one shown above. Now remove the logically
unnecessary = 0
initialization for val
so the line is just int val;
.
As the comment says, an error should
appear (at least after you try to compile the program).
The error will say that there is an uninitialized local variable! Why?
For safety
the C# compiler has some basic analysis to check that every local
variable gets given a value before its value is used. In the OkScope
function
there is no one
place where val
gets an initial value, but the compiler is smart enough to see
that one of the branches of any if-else statement is always taken,
and val
gets a value in each, so there is
no problem.
The compiler analysis is not complete: It does not actually evaluate any
expressions. This is good enough to catch many initialization errors that coders make,
but it
is not sufficient in general: We can see this from the altered OkScope2
.
The original code shows the fix: Give a dummy initialization that is never used in execution, but keeps the compiler happy.
Although this extra initialization is annoying, the extra step is rarely needed. Meanwhile it is very easy to forget to give a value to a local variable before use! Having the error caught quickly by the compiler is very handy, offsetting the extra work when the compiler gives this error unnecessarily.
If-else Exercise
Think of two different inputs you could give that would make the execution of the code fragment proceed differently. What would happen in each case? (Assume we have access to the class UIF.)
Consider:
string v = UIF.PromptLine("Enter a word: "); if (v.Length > 3) { v = v + v; Console.WriteLine("Now we have " + v); } else { Console.WriteLine("We still have " + v); }
Consider:
int x = UIF.PromptInt("Enter a integer: "); Console.Write("The magnitude of " + x + " is "); if (x < 0) { Console.WriteLine(-x); } else { Console.WriteLine(x); }