In the following code, how would you refer to the
namespace fabulous { // code in fabulous namespace } namespace super { namespace smashing { // great name defined } }
Which of the following is not a legal variable name?
myVariableIsGood
99Flake
_floor
time2GetJiggyWidIt
wrox.com
Is the string "supercalifragilisticexpialidocious" too big to fit in a string variable? Why?
By considering operator precedence, list the steps involved in the computation of the following expression:
resultVar += var1 * var2 + var3 % var4 / var5;
Write a console application that obtains four
int
values from the
All of the C# code you've seen so far has had one thing in common. In each case, program execution has proceeded from one line to the
In this chapter, you look at two methods of controlling program flow, that is, the order of execution of lines of C# code. These two
Branching , where you execute code conditionally, depending on the outcome of an evaluation, such as "only execute this code if myVal is less than 10."
Looping , or repeatedly executing the same statements (for a certain number of times or until a test condition has been reached).
Both of these techniques involve the use of
Boolean logic
. In the last chapter you saw the
bool
type, but didn't actually do much with it. In this chapter you use it a lot, and so the chapter will start by discussing what is
The bool type introduced in the last chapter can hold one of only two values, true or false . This type is often used to record the result of some operation, so that you can act on this result. In particular, bool types are used to store the result of a comparison .
| Note |
As an historical aside, it is worth remembering (and respecting) the English
|
As an example, consider the situation (as mentioned in the introduction to this chapter) that you want to execute code based on whether a variable, myVal , is less than 10. To do this, you need some indication of whether the statement " myVal is less than 10" is true or false, that is, you need to know the Boolean result of a comparison.
Boolean comparisons require the use of Boolean comparison operators (also known as relational operators), which are shown in the following table. In all cases here var1 is a bool type variable, while the types of var2 and var3 may vary.
|
Operator |
Category |
Example Expression |
Result |
|---|---|---|---|
|
== |
Binary |
var1 = var2 == var3; |
var1
is assigned the value
true
if
var2
is equal to
var3
, or
false
|
|
!= |
Binary |
var1 = var2 != var3; |
var1 is assigned the value true if var2 is not equal to var3 , or false otherwise. |
|
< |
Binary |
var1 = var2 < var3; |
var1 is assigned the value true if var2 is less than var3 , or false otherwise. |
|
> |
Binary |
var1 = var2 > var3; |
var1 is assigned the value true if var2 is greater than var3 , or false otherwise. |
|
<= |
Binary |
var1 = var2 <= var3; |
var1 is assigned the value true if var2 is less than or equal to var3 , or false otherwise. |
|
>= |
Binary |
var1 = var2 >= var3; |
var1 is assigned the value true if var2 is greater than or equal to var3 , or false otherwise. |
You might use operators such as these on numeric values in code such as:
bool isLessThan10; isLessThan10 = myVal < 10;
This code will result in isLessThan10 being assigned the value true if myVal stores a value less than 10, or false otherwise.
You can also use these comparison operators on other types, such as strings:
bool isKarli; isKarli = myString == "Karli";
Here, isKarli will only be true if myString stores the string "Karli" .
You can also focus on Boolean values:
bool isTrue; isTrue = myBool == true;
although here you are limited to the use of == and != operators.
| Note |
Note that a common code error occurs if you unintentionally assume that because val1 < val2 is false, then val1 > val2 is true. If val1 == val2 then both these statements will be false. I'm mentioning this here because it's a mistake I've made in the past! |
There are some other Boolean operators that are intended
|
Operator |
Category |
Example Expression |
Result |
|---|---|---|---|
|
! |
Unary |
var1 = ! var2; |
var1 is assigned the value true if var2 is false , or false if var2 is true . (Logical NOT.) |
|
& |
Binary |
var1 = var2 & var3; |
var1 is assigned the value true if var2 and var3 are both true , or false otherwise. (Logical AND.) |
|
|
Binary |
var1 = var2 var3; |
var1 is assigned the value true if either var2 or var3 (or both) are true , or false otherwise. (Logical OR.) |
|
^ |
Binary |
var1 = var2 ^ var3; |
var1 is assigned the value true if either var2 or var3 , but not both, are true, or false otherwise. (Logical XOR, or exclusive OR.) |
So, the last code snippet above could also be
bool isTrue; isTrue = myBool & true;
The
&
and
operators also have two similar operators, known as
conditional Boolean
operators, shown in the
|
Operator |
Category |
Example Expression |
Result |
|---|---|---|---|
|
&& |
Binary |
var1 = var2 && var3; |
var1 is assigned the value true if var2 and var3 are both true , or false otherwise. (Logical AND.) |
|
|
Binary |
var1 = var2 var3; |
var1 is assigned the value true if either var2 or var3 (or both) are true, or false otherwise. (Logical OR.) |
The result of these operators is exactly the same as
&
and
, but there is an important difference in the way this result is obtained, which can result in better performance. Both of these look at the value of their first operand (
var2
in the
If the value of the first operand of the && operator is false , then there is no need to consider the value of the second operand, because the result will be false regardless. Similarly, the operator will return true if its first operand is true , regardless of the value of the second operand.
This isn't the case for the & and operators you saw earlier. With these, both operands will always be evaluated.
Because of this conditional evaluation of operands, you will see a small performance increase if you use && and instead of & and . This will be particularly apparent in applications that use these operators a lot. As a rule of thumb, always use && and where possible.
Note that these operators really come into their own in more complicated situations, where computation of the second operand is only possible with certain values of the first operand, for example:
var1 = (var2 != 0) && (var3 / var2 > 2);
Here, if var2 is zero then dividing var3 by var2 will result in either a "division by zero" error or var1 being defined as infinite (the latter is possible, and detectable, with some types such as float ).
In the light of the discussion in the last section, you may be asking why the
&
and
operators exist at all. The reason is that these operators may be used to perform operations on numeric values. In fact, they
Let's consider these in
|
Operand 1 Bit |
Operand 2 Bit |
& Result Bit |
|---|---|---|
|
1 |
1 |
1 |
|
1 |
|
|
|
|
1 |
|
|
|
|
|
is similar, but the result bits are different, as shown in the next table.
|
Operand 1 Bit |
Operand 2 Bit |
Result Bit |
|---|---|---|
|
1 |
1 |
1 |
|
1 |
|
1 |
|
|
1 |
1 |
|
|
|
|
For example, consider the operation shown in the following code:
int result, op1, op2; op1 = 4; op2 = 5; result = op1 & op2;
Here, you must consider the binary representations of
op1
and
op2
, which are 100 and 101, respectively. The result is obtained by comparing the binary digits in equivalent
The leftmost bit of result is 1 if the leftmost bit of op1 and op2 are both 1, or 0 otherwise.
The next bit of result is 1 if the next bit of op1 and op2 are both 1, or 0 otherwise.
Continue for all remaining bits.
In this example, the leftmost bits of op1 and op 2 are both 1, so the leftmost bit of result will be 1, too. The next bits are both 0, and the third bits are 1 and 0, respectively, so the second and third bits of result will be 0. The final value of result in binary representation is, therefore, 100, so result is assigned the value 4. This is shown graphically in the following table.
|
1 |
|
|
4 |
|||
|
& |
1 |
|
1 |
& |
5 |
|
|
1 |
|
|
4 |
The same process occurs if you use the operator, except that in this case each result bit is 1 if either of the operand bits in the same position is 1. This is shown in the next table.
|
1 |
|
|
4 |
|||
|
|
1 |
|
1 |
|
5 |
|
|
1 |
|
1 |
5 |
You can also use the Δ ^ operator in the same way, where each result bit is 1 if one or other of the operand bits in the same position is one, but not both, as shown in the following table.
|
Operand 1 Bit |
Operand 2 Bit |
^ Result Bit |
|---|---|---|
|
1 |
1 |
|
|
1 |
|
1 |
|
|
1 |
1 |
|
|
|
|
C# also allows the use of a unary bitwise operator ( ~ ), which acts on its operand by inverting each of its bits, such that the result is a variable having values of 1 for each bit in the operand that is 0, and vice versa: This is shown in the following table.
|
Operand Bit |
~ Result Bit |
|---|---|
|
1 |
|
|
|
1 |