CHAPTER 11

image

Statements and Flow of Execution

The following sections detail the different statements that are available within the C# language.

Selection Statements

The selection statements are used to perform operations based on the value of an expression.

If

The if statement in C# requires that the condition inside the if statement evaluate to an expression of type bool. In other words, the following is illegal:1

// error
using System;
class Test
{
    public static void Main()
    {
       int value = 0;
       if (value)       // invalid
       {
            System.Console.WriteLine("true");
       }
       if (value == 0)    // must use this
       {
            System.Console.WriteLine("true");
       }
    }
}

Switch

Switch statements have often been error-prone; it is just too easy to inadvertently omit a break statement at the end of a case or, more likely, not to notice that there is fall-through when reading code.

C# gets rid of this possibility by requiring a flow-of-control statement (such as a break or goto, another case label) at the end of every case block.

using System;
class Test
{
    public void Process(int i)
    {
       switch (i)
       {
            case 1:
            case 2:
                // code here handles both 1 and 2
                Console.WriteLine("Low Number");
                break;
            case 3:
                Console.WriteLine("3");
                goto case 4;
            case 4:
                Console.WriteLine("Middle Number");
                break;
            default:
                Console.WriteLine("Default Number");
                break;
       }
    }
}

C# also allows the switch statement to be used with string variables.

using System;
class Test
{
    public void Process(string htmlTag)
    {
       switch (htmlTag)
       {
            case "P":
                Console.WriteLine("Paragraph start");
                break;
            case "DIV":
                Console.WriteLine("Division");
                break;
            case "FORM":
                Console.WriteLine("Form Tag");
                break;
            default:
                Console.WriteLine("Unrecognized tag");
                break;
       }
    }
}

Not only is it easier to write a switch statement than a series of if statements, but it’s also more efficient, because the compiler uses an efficient algorithm to perform the comparison.

For small numbers of entries2 in the switch, the compiler uses a feature in the .NET Runtime known as string interning. The runtime maintains an internal table of all constant strings so that all occurrences of that string in a single program will have the same object. In the switch, the compiler looks up the switch string in the runtime table. If it isn’t there, the string can’t be one of the cases, so the default case is called. If it is found, a sequential search is done of the interned case strings to find a match.

For larger numbers of entries in the case, the compiler generates a hash function and hash table and uses the hash table to efficiently look up the string.3

Iteration Statements

Iteration statements are often known as looping statements, and they are used to perform operations while a specific condition is true.

While

The while loop functions as expected: while the condition is true, the loop is executed. Like the if statement, the while requires a Boolean condition.

using System;
class Test
{
    public static void Main()
    {
       int n = 0;
       while (n < 10)
       {
            Console.WriteLine("Number is {0}", n);
            n++;
       }
    }
}

The break statement can be used to exit the while loop, and the continue statement can be used to skip to the closing brace of the while block for this iteration and then continue with the next iteration.

using System;
class Test
{
    public static void Main()
    {
       int n = 0;
       while (n < 10)
       {
            if (n == 3)
            {
                n++;
                continue; //don't print 3
            }
            if (n == 8)
            {
                break;
            }
            Console.WriteLine("Number is {0}", n);
            n++;
       }
    }
}

This code will generate the following output:

0
1
2
4
5
6
7

Do

A do loop functions just like a while loop, except the condition is evaluated at the end of the loop rather than the beginning of the loop.

using System;
class Test
{
    public static void Main()
    {
       int n = 0;
       do
       {
            Console.WriteLine("Number is {0}", n);
            n++;
       } while (n < 10);
    }
}

Like the while loop, the break and continue statements can be used to control the flow of execution in the loop.

For

A for loop is used to iterate over several values. The loop variable may be declared as part of the for statement.

using System;
class Test
{
    public static void Main()
    {
       for (int n = 0; n < 10; n++)
       {
            Console.WriteLine("Number is {0}", n);
       }
    }
}

The scope of the loop variable in a for loop is the scope of the statement or statement block that follows the for. It cannot be accessed outside of the loop structure.

// error
using System;
class Test
{
    public static void Main()
    {
       for (int n = 0; n < 10; n++)
       {
            if (n == 8)
            {
                break;
            }
            Console.WriteLine("Number is {0}", n);
       }
            // error; n is out of scope
       Console.WriteLine("Last Number is {0}", n);
    }
}

As with the while loop, the break and continue statements can be used to control the flow of execution in the loop.

Foreach

This is a very common looping idiom:

using System;
using System.Collections.Generic;
class MyObject
{
}
class Test
{
    public static void Process(List < MyObject > items)
    {
       for (int nIndex = 0; nIndex < items.Count; nIndex++)
       {
            MyObject current = items[nIndex];
            Console.WriteLine("Item: {0}", current);
       }
    }
}

This works fine, but it requires the programmer to ensure that the array in the for statement matches the array that is used in the indexing operation. If they don’t match, it can sometimes be difficult to track down the bug. It also requires declaring a separate index variable, which could accidentally be used elsewhere.

It’s also a lot of typing.

Some languages4 provide a different construct for dealing with this problem, and C# also provides such a construct. The preceding example can be rewritten as follows:

using System;
using System.Collections.Generic;
class MyObject
{
}
class Test
{
    public static void Process(List < MyObject > items)
    {
       foreach (MyObject current in items)
       {
            Console.WriteLine("Item: {0}", current);
       }
    }
}

Foreach works for any object that implements the proper interfaces. It can, for example, be used to iterate over the keys of a hash table.

using System;
using System.Collections;
class Test
{
    public static void Main()
    {
       Hashtable hash = new Hashtable();
       hash.Add("Fred", "Flintstone");
       hash.Add("Barney", "Rubble");
       hash.Add("Mr.", "Slate");
       hash.Add("Wilma", "Flintstone");
       hash.Add("Betty", "Rubble");
       foreach (string firstName in hash.Keys)
       {
            Console.WriteLine("{0} {1}", firstName, hash[firstName]);
       }
    }
}

User-defined objects can be implemented so that they can be iterated over using foreach; see the “Indexers and Foreach” section in Chapter 20 for more information.

The one thing that can’t be done in a foreach loop is changing the contents of the container. In other words, in the previous example, the firstName variable can’t be modified. If the container supports indexing, the contents could be changed through that route, though many containers that enable use by foreach don’t provide indexing. Another thing to watch is to make sure the container isn’t modified during the foreach; the behavior in such situations is undefined.5

As with other looping constructs, break and continue can be used with the foreach statement.

Jump Statements

Jump statements are used to do just that—jump from one statement to another.

Break

The break statement is used to break out of the current iteration or switch statement and continue execution after that statement.

Continue

The continue statement skips all of the later lines in the current iteration statement and then continues executing the iteration statement.

Goto

The goto statement can be used to jump directly to a label. Because the use of goto statements is widely considered to be harmful,6 C# prohibits some of their worst abuses. A goto cannot be used to jump into a statement block, for example. The only place where their use is recommended is in switch statements or to transfer control to outside a nested loop,7 though they can be used elsewhere.

Return

The return statement returns to the calling function and optionally returns a value.

Other Statements

The following statements are covered in other chapters.

lock

The lock statement is used to provide exclusive access to a thread. See the section on threads in Chapter 35.

using

The using statement is used in two ways. The first is to specify namespaces, which is covered in Chapter 2. The second use is to ensure that Dispose() is called at the end of a block, which is covered in detail in Chapter 7.

try, catch, and finally

The try, catch, and finally statements are used to control exception handling and are covered in Chapter 3.

checked and unchecked

The checked and unchecked statements control whether exceptions are thrown if conversions or expressions overflow and are covered in Chapter 13.

yield

The yield statement is used to implement iterators, covered in Chapter 19.

1 In C and C++, it is possible to accidentally write if (x = 1), which is an assignment rather than a conditional and therefore is always true. The C# behavior eliminates this issue.

2 The actual number is determined based upon the performance trade-offs of each method.

3 If you’re unfamiliar with hashing, consider looking at the System.Collections.HashTable class or a good algorithms book.

4 Depending on your language background, this might be Perl or Visual Basic.

5 It is recommended that a container throw an exception in this case, though it may be expensive to detect the condition.

6 See “GO TO considered harmful” by Edsger W. Dijkstra.

7 I’ve written a lot of C# code in the past few years, and never once have I been tempted to use a goto.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.162.65