Welcome PradhiKarthik: VC#. NET

Sunday, September 19, 2010

VC#. NET

 C# Programming Language

Getting Started:

This lesson will get you started with C# by introducing a few very simple programs. Here are the objectives of this lesson:

Understand the basic structure of a C# program.
Obtain a basic familiarization of what a "Namespace" is.
Obtain a basic understanding of what a Class is.
Learn what a Main method does.
Learn how to obtain command-line input.
Learn about console input/output (I/O).

A Simple C# Program

What we'll do is start off with a real simple C# program.This will explain some of the basic concepts that will follow for all C# programs you will build.  For example, you need to know how to start a program, how to structure the code, and gain some familiarity with the syntax of a C# program. Listing 1-1 shows this simple program.
Warning: C# is case-sensitive.
Listing 1-1. A Simple Welcome Program: Welcome.cs
// Namespace Declaration
using System;
// Program start class
class WelcomeCSS
{
    // Main begins program execution.
    public static void Main()
    {
        // Write to console
        Console.WriteLine("Welcome to the C# Training!");
    }
}
The program in Listing 1-1 has 4 primary elements, a namespace declaration, a class, a Main method, and a program statement.  It can be compiled with the following command line:
csc.exe Welcome.cs
Get Setup Instructions For How to Run this Program
This produces a file named Welcome.exe, which can then be executed. Other programs can be compiled similarly by substituting their file name instead of Welcome.cs. For more help about command line options, type "csc -help" on the command line. The file name and the class name can be totally different.
Note for VS.NET Users: The screen will run and close quickly when launching this program from Visual Studio .NET.; To prevent this add the following code as the last line in the Main method:
// keep screen from going away
// when run from VS.NET
Console.ReadLine();
Note: The command-line is a window that allows you to run commands and programs by typing the text in manually. It is often refered to as the DOS prompt, which was the operating system people used years ago, before Windows. 
The first thing you should be aware of is that C# is case-sensitive. The word "Main" is not the same as its lower case spelling, "main". They are different identifiers. If you are coming from a language that is not case sensitive, this will trip you up several times until you become accustomed to it.
The namespace declaration, using System;, indicates that you are referencing the System namespace. Namespaces contain groups of code that can be called upon by C# programs. With the using System; declaration, you are telling your program that it can reference the code in the System namespace without pre-pending the word System to every reference. I'll discuss this in more detail in Lesson 06: Namespaces, which is dedicated specifically to namespaces.
The class declaration, class WelcomeCSS, contains the data and method definitions that your program uses to execute. A class is one of a few different types of elements your program can use to describe objects, such as interfaces and structures, which will be discussed in more detail in Lesson 13: Interfaces and Lesson 12: Structs , respectively. This particular class has no data, but it does have one method. This method defines the behavior of this class (or what it is capable of doing). I'll discuss classes more in Lesson 07: Introduction to Classes. We'll be covering a lot of information about classes throughout this Training.
The one method within the WelcomeCSS class tells what this class will do when executed. The method name, Main, is reserved for the starting point of a program. Main is often called the "entry point" and if you ever receive a compiler error message saying that it can't find the entry point, it means that you tried to compile an executable program without a Main method.
Before the word Main is a static modifier. The static modifier explains that this method works in this specific class only, rather than an instance of the class. This is necessary, because when a program begins, no object instances exist. I'll tell you more about classes, objects, and instances in Lesson 07: Introduction to Classes.
Every method must have a return type. In this case it is void, which means that Main does not return a value. Every method also has a parameter list following its name with zero or more parameters between parenthesis. For simplicity, we did not add parameters to Main. Later in this lesson you'll see what type of parameter the Main method can have. You'll learn more about methods in Lesson 05: Methods.

The Main method specifies its behavior with the Console.WriteLine(...) statement. Console is a class in the System namespace. WriteLine(...) is a method in the Console class. We use the ".", dot, operator to separate subordinate program elements. Note that we could also write this statement as System.Console.WriteLine(...). This follows the pattern "namespace.class.method" as a fully qualified statement. Had we left out the using System declaration at the top of the program, it would have been mandatory for us to use the fully qualified form System.Console.WriteLine(...). This statement is what causes the string, "Welcome to the C# Training!" to print on the console screen.
Observe that comments are marked with "//". These are single line comments, meaning that they are valid until the end-of-line. If you wish to span multiple lines with a comment, begin with "/*" and end with "*/". Everything in between is part of the comment. You can place a single line comment within a multi-line comment. However, you can't put multi-line comments within a multi-line comment. Comments are not considered when your program is compiled. They are there to document what your program does in plain English (or the native language you speak with every day).
All statements end with a ";", semi-colon. Classes and methods begin with "{", left curly brace, and end with a "}", right curly brace. Any statements within and including "{" and "}" define a block. Blocks define scope (or lifetime and visibility) of program elements.
Accepting Command-Line Input
Many programs are written to accept command-line input. Collection of command-line input occurs in the Main method. Listing 1-2 shows a program which accepts a name from the command line and writes it to the console.
Listing 1-2. Getting Command-Line Input: NamedWelcome.cs
// Namespace Declaration
using System;

// Program start class
class NamedWelcome
{
    // Main begins program execution.
    public static void Main(string[] args)
    {
        // Write to console
        Console.WriteLine("Hello, {0}!", args[0]);
        Console.WriteLine("Welcome to the C# Training!");
    }
}
C:\>NamedWelcome.exe
Get Setup Instructions For How to Run this Program
Remember to add your name to the command-line, i.e. "NamedWelcome Prasad". If you don't, your program will crash. I'll show you in Lesson 15: Introduction to Exception Handling how to detect and avoid such error conditions.
In Listing 1-2, you'll notice an entry in the Main method's parameter list. The parameter name is args. It is what you'll use to refer to the parameter later in your program. The string[] expression defines the type of parameter that args is. The string type holds characters. These characters could form a single word, or multiple words. The "[]", square brackets denote an Array, which is like a list. Therefore, the type of the args parameter, is a list of words from the command-line.
You'll also notice an additional Console.WriteLine(...) statement within the Main method. The argument list within this statement is different than before. It has a formatted string with a "{0}" parameter embedded in it. The first parameter in a formatted string begins at number 0, the second is 1, and so on. The "{0}" parameter means that the next argument following the end quote will determine what goes in that position. Hold that thought, and now we'll look at the next argument following the end quote.

This is the args[0] argument, which refers to the first string in the args array. The first element of an Array is number 0, the second is number 1, and so on. For example, if I wrote "NamedWelcome Prasad" on the command-line, the value of args[0] would be "Prasad".
Now we'll get back to the embedded "{0}" parameter in the formatted string. Since args[0] is the first argument, after the formatted string, of the Console.WriteLine() statement, its value will be placed into the first embedded parameter of the formatted string. When this command is executed, the value of args[0], which is "Prasad" will replace "{0}" in the formatted string. Upon execution of the command-line with "NamedWelcome Prasad", the output will be as follows:
Hello, Prasad!Welcome to the C# Training!
Interacting via the Command-Line
Another way to provide input to a program is via the Console. Typically, it works like this: You prompt the user for some input, they type something in and press the Enter key, and you read their input and take some action in your program. Listing 1-3 shows how to obtain interactive input from the user.
Listing 1-3. Getting Interactive Input: InteractiveWelcome.cs
// Namespace Declaration
using System;

// Program start class
class InteractiveWelcome
{
    // Main begins program execution.
    public static void Main()
    {
        // Write to console/get input
        Console.Write("What is your name?: ");
        Console.Write("Hello, {0}! ", Console.ReadLine());
        Console.WriteLine("Welcome to the C# Training!");
    }
}
Get Setup Instructions For How to Run this Program
In Listing 1-3, the Main method doesn't have any parameters -- mostly because it isn't necessary this time. However, there are now three statements and the first two are different from the third. They are Console.Write(...) instead of Console.WriteLine(...). The difference is that the Console.Write(...) statement writes to the console and stops on the same line, but the Console.WriteLine(...) goes to the next line after writing to the console.
The first statement simply writes "What is your name?: " to the console.
The second statement doesn't write anything until its arguments are properly evaluated. The first argument after the formatted string is Console.ReadLine().  This causes the program to wait for user input at the console. After the user types input, their name in this case, they must press the Enter key. The return value from this method replaces the "{0}" parameter of the formatted string and is written to the console. This line could have also been written like this:
string name = Console.ReadLine();
Console.Write("Hello, {0}! ", name);
The last statement writes to the console as described earlier.  Upon execution of the command-line with "InteractiveWelcome", the output will be as follows:
>What is your Name?  [Enter Key]
>Hello, !  Welcome to the C# Training!
Summary
By now you know the basic structure of a C# program. using statements let you reference a namespace and allow code to have shorter and more readable notation. The Main method is the entry point to start a C# program. You can capture command-line input when an application is run by reading items from a string[] (string array) parameter to your Main method. Interactive I/O can be performed with the ReadLine, Write and WriteLine methods of the Console class.

Lesson 2: Operators, Types, and Variables

This lesson introduces C# operators, types, and variables.  Its goal is to meet the following objectives:
  • Understand what a variable is.
  • Familiarization with C# built-in types.
  • Get an introduction to C# operators.
  • Learn how to use Arrays.

Variables and Types

"Variables" are simply storage locations for data. You can place data into them and retrieve their contents as part of a C# expression. The interpretation of the data in a variable is controlled through "Types".
C# is a strongly "Typed" language. Thus all operations on variables are performed with consideration of what the variable's "Type" is. There are rules that define what operations are legal in order to maintain the integrity of the data you put in a variable.
The C# simple types consist of the Boolean type and three numeric types - Integrals, Floating Point, Decimal and String. The term "Integrals" refers to the classification of types that include sbyte, byte, short, ushort, int, uint, long, ulong, and char. More details are available in the Integral Types section later in this lesson. The term "Floating Point" refers to the float and double types, which are discussed, along with the decimal type, in more detail in the Floating Point and Decimal Types section later in this lesson. The string type represents a string of characters and is discussed in The String Type section, later in this lesson. The next section introduces the boolean type.

The Boolean Type

Boolean types are declared using the keyword, bool. They have two values: true or false. In other languages, such as C and C++, boolean conditions can be satisfied where 0 means false and anything else means true. However, in C# the only values that satisfy a boolean condition is true and false, which are official keywords. Listing 2-1 shows one of many ways that boolean types can be used in a program.
Listing 2-1. Displaying Boolean Values: Boolean.cs
using System;

class
Booleans
{
    public static void Main()
    {
        bool content = true;
        bool noContent = false;

        Console.WriteLine("It is {0} that C# Station provides C# programming language content.", content);
        Console.WriteLine("The statement above is not {0}.", noContent);
    }
}

Get Setup Instructions For How to Run this Program
In Listing 2-1, the boolean values are written to the console as a part of a sentence. The only legal values for the bool type are either true or false, as shown by the assignment of true to content and false to noContent. When run, this program produces the following output:
It is True that C# Station provides C# programming language content.
 
The statement above is not False. 

Integral Types

In C#, an integral is a category of types. They are whole numbers, either signed or unsigned, and the char type. The char type is a Unicode character, as defined by the Unicode Standard.Table 2-1 shows the integral types, their size, and range.
Table 2-1. The Size and Range of C# Integral Types
Type
Size (in bits)
Range
sbyte
8
-128 to 127
byte
8
0 to 255
short
16
-32768 to 32767
ushort
16
0 to 65535
int
32
-2147483648 to 2147483647
uint
32
0 to 4294967295
long
64
-9223372036854775808 to 9223372036854775807
ulong
64
0 to 18446744073709551615
char
16
0 to 65535
Integral types are well suited for those operations involving whole number calculations. The char type is the exception, representing a single Unicode character. As you can see from the table above, you have a wide range of options to choose from, depending on your requirements.

Floating Point and Decimal Types

A C# floating point type is either a float or double. They are used any time you need to represent a real number, as defined by IEEE 754.Decimal types should be used when representing financial or money values. Table 2-2 shows the floating point and decimal types, their size, precision, and range.
Table 2-2. The Floating Point and Decimal Types with Size, Precision, and Range
Type
Size (in bits)
Precision
Range
float
32
7 digits
1.5 x 10-45 to 3.4 x 1038
double
64
15-16 digits
5.0 x 10-324 to 1.7 x 10308
decimal
128
28-29 decimal places
1.0 x 10-28 to 7.9 x 1028
Floating point types are used when you need to perform operations requiring fractional representations. However, for financial calculations, the decimal type is the best choice because you can avoid rounding errors.

The string Type

A string is a string of text characters. You typically create a string with a string literal, enclosed in quotes: "This is an example of a string." You've seen strings being used since Lesson 1, where we used the Console.WriteLine method to send output to the console.
Some characters aren't printable, but you still need to use them in strings. Therefore, C# has a special syntax where characters can be escaped to represent non-printable characters. For example, it is common to use newlines in text, which is represented by the '\n' char. The backslash, '\', represents the escape. When preceded by the escape character, the 'n' is no longer interpreted as an alphabetical character, but now represents a newline.
You may be now wondering how you could represent a backslash character in your code. We have to escape that too by typing two backslashes, as in '\\'. Table 2-3 shows a list of common escape sequences.
Table 2-3. C# Character Escape Sequences
Escape Sequence
Meaning
\'
Single Quote
\"
Double Quote
\\
Backslash
\0
Null, not the same as the C# null value
\a
Bell
\b
Backspace
\f
Form Feed
\n
Newline
\r
Carriage Return
\t
Horizontal Tab
\v
Vertical Tab
Another useful feature of C# strings is the verbatim literal, which is a string with a @ symbol prefix, as in @"Some string". Verbatim literals make escape sequences translate as normal characters to enhance readability. To appreciate the value of verbatim literals, consider a path statement such as "c:\\topdir\\subdir\\subdir\\myapp.exe". As you can see, the backslashes are escaped, causing the string to be less readable. You can improve the string with a verbatim literal, like this: @"c:\topdir\subdir\subdir\myapp.exe".

C# Operators

Results are computed by building expressions.  These expressions are built by combining variables and operators together into statements.  The following table describes the allowable operators, their precedence, and associativity.
Table 2-4. Operators with their Precedence and Associativity
Category (by precedence)
Operator(s) 
Associativity
Primary
(x)  x.y  f(x)  a[x]  x++  x--  new  typeof  sizeof  checked  unchecked
left
Unary
+  -  !  ~  ++x  --x  (T)x
left
Multiplicative
*  /  %
left
Additive
+  -
left
Shift
<<  >>
left
Relational
<  >  <=  >=  is
left
Equality
==  !=
right
Logical AND
&
left
Logical XOR
^
left
Logical OR
|
left
Conditional AND
&&
left
Conditional OR
||
left
Conditional>
?:
right
Assignment
=  *=  /=  %=  +=  -=  <<=  >>=  &=  ^=  |=
right
Left associativity means that operations are evaluated from left to right. Right associativity mean all operations occur from right to left, such as assignment operators where everything to the right is evaluated before the result is placed into the variable on the left.
Most operators are either unary or binary. Unary operators form expressions on a single variable, but binary operators form expressions with two variables. Listing 2-2 demonstrates how unary operators are used.
Listing 2-2. Unary Operators: Unary.cs
using System;

class Unary
{
    public static void Main()
    {
        int unary = 0;
        int preIncrement;
        int preDecrement;
        int postIncrement;
        int postDecrement;
        int positive;
        int negative;
        sbyte bitNot;
        bool logNot;

        preIncrement = ++unary;
        Console.WriteLine("Pre-Increment: {0}", preIncrement);

        preDecrement = --unary;
        Console.WriteLine("Pre-Decrement: {0}", preDecrement);

        postDecrement = unary--;
        Console.WriteLine("Post-Decrement: {0}", postDecrement);

        postIncrement = unary++;
        Console.WriteLine("Post-Increment: {0}", postIncrement);

        Console.WriteLine("Final Value of Unary: {0}", unary);

        positive = -postIncrement;
        Console.WriteLine("Positive: {0}", positive);

        negative = +postIncrement;
        Console.WriteLine("Negative: {0}", negative);

        bitNot = 0;
        bitNot = (sbyte)(~bitNot);
        Console.WriteLine("Bitwise Not: {0}", bitNot);

        logNot = false;
        logNot = !logNot;
        Console.WriteLine("Logical Not: {0}", logNot);
    }
}

Get Setup Instructions For How to Run this Program
When evaluating expressions, post-increment (x++) and post-decrement (x--) operators return their current value and then apply the operators. However, when using pre-increment (++x) and pre-decrement (--x) operators, the operator is applied to the variable prior to returning the final value.
In Listing 2-2, the unary variable is initialized to zero. When the pre-increment (++x) operator is used, unary is incremented to 1 and the value 1 is assigned to the preIncrement variable. The pre-decrement (--x) operator turns unary back to a 0 and then assigns the value to the preDecrement variable.
When the post-decrement (x--) operator is used, the value of unary, 0, is placed into the postDecrement variable and then unary is decremented to -1. Next the post-increment (x++) operator moves the current value of unary, -1, to the postIncrement variable and then increments unary to 0.
The variable bitNot is initialized to zero and the bitwise not (~) operator is applied. The bitwise not (~) operator flips the bits in the variable. In this case, the binary representation of 0, "00000000", was transformed into -1, "11111111".
Notice the expression (sbyte)(~bitNot). Any operation performed on types sbyte, byte, short, or ushort return int values. To assign the result into the bitNot variable we had to use a cast (Type) operator, where Type is the type you wish to convert to (in this case - sbyte). The cast operator is shown as the Unary operator "(T)x" in Table 2-4. Cast operators must be performed explicity when you go from a larger type to a smaller type because of the potential for lost data. Generally speaking, assigning a smaller type to a larger type is no problem, since the larger type has room to hold the entire value. Also be aware of the dangers of casting between signed and unsigned types. You want to be sure to preserve the integrity of your data. Many basic programming texts contain good descriptions of bit representations of variables and the dangers of explicit casting.
The logical not (!) operator allows you to toggle the value of a boolean variable. In the example, the logNot variable is changed from false to true. You can expect the following output from the above program.
Pre-Increment: 1
 
Pre-Decrement 0
 
Post-Decrement: 0
 
Post-Increment: -1
 
Final Value of Unary: 0
 
Positive: 1
 
Negative: -1
 
Bitwise Not: -1
 
Logical Not: True 
In addition to unary operators, C# has binary operators that form expressions of two variables. Listing 2-3 shows how to use the binary operators.
Listing 2-3. Binary Operators: Binary.cs
using System;

class Binary
{
    public static void Main()
    {
        int x, y, result;
        float floatResult;

        x = 7;
        y = 5;

        result = x+y;
        Console.WriteLine("x+y: {0}", result);

        result = x-y;
        Console.WriteLine("x-y: {0}", result);

        result = x*y;
        Console.WriteLine("x*y: {0}", result);

        result = x/y;
        Console.WriteLine("x/y: {0}", result);

        floatResult = (float)x/(float)y;
        Console.WriteLine("x/y: {0}", floatResult);

        result = x%y;
        Console.WriteLine("x%y: {0}", result);

        result += x;
        Console.WriteLine("result+=x: {0}", result);
    }
}

And here's the output:
x+y: 12 
 
x-y: 2 
 
x*y: 35 
 
x/y: 1 
 
x/y: 1.4 
 
x%y: 2 
 
result+=x: 9
Get Setup Instructions For How to Run this Program
Listing 2-3 shows several examples of binary operators. As you might expect, the results of addition (+), subtraction (-), multiplication (*), and division (/) produce the expected mathematical results.
The floatResult variable is a floating point type. We explicitly cast the integer variables x and y to calculate a floating point value.
There is also an example of the remainder(%) operator. It performs a division operation on two values and returns the remainder.
The last statement shows another form of the assignment with operation (+=) operator. Any time you use the assignment with operation operator, it is the same as applying the binary operator to both the left hand and right hand sides of the operator and putting the results into the left hand side. The example could have been written as result = result + x; and returned the same value.

The Array Type

Another data type is the Array, which can be thought of as a container that has a list of storage locations for a specified type. When declaring an Array, specify the type, name, dimensions, and size.
Listing 2-4. Array Operations: Array.cs
using System;

class Array
{
    public static void Main()
    {
        int[] myInts = { 5, 10, 15 };
        bool[][] myBools = new bool[2][];
        myBools[0] = new bool[2];
        myBools[1] = new bool[1];
        double[,] myDoubles = new double[2, 2];
        string[] myStrings = new string[3];

        Console.WriteLine("myInts[0]: {0}, myInts[1]: {1}, myInts[2]: {2}", myInts[0], myInts[1], myInts[2]);

        myBools[0][0] = true;
        myBools[0][1] = false;
        myBools[1][0] = true;
        Console.WriteLine("myBools[0][0]: {0}, myBools[1][0]: {1}", myBools[0][0], myBools[1][0]);

        myDoubles[0, 0] = 3.147;
        myDoubles[0, 1] = 7.157;
        myDoubles[1, 1] = 2.117;
        myDoubles[1, 0] = 56.00138917;
        Console.WriteLine("myDoubles[0, 0]: {0}, myDoubles[1, 0]: {1}", myDoubles[0, 0], myDoubles[1, 0]);

        myStrings[0] = "Joe";
        myStrings[1] = "Matt";
        myStrings[2] = "Robert";
        Console.WriteLine("myStrings[0]: {0}, myStrings[1]: {1}, myStrings[2]: {2}", myStrings[0], myStrings[1], myStrings[2]);

    }
}

And here's the output:
myInts[0]: 5, myInts[1]: 10, myInts[2]: 15
 
myBools[0][0]: True, myBools[1][0]: True
 
myDoubles[0, 0]: 3.147, myDoubles[1, 0]: 56.00138917
 
myStrings[0]: Joe, myStrings[1]: Matt, myStrings[2]: Robert
Get Setup Instructions For How to Run this Program
Listing 2-4 shows different implementations of Arrays. The first example is the myInts Array. It is initialized at declaration time with explicit values.
Next is a jagged array. It is essentially an array of arrays. We needed to use the new operator to instantiate the size of the primary array and then use the new operator again for each sub-array.
The third example is a two dimensional array. Arrays can be multi-dimensional, with each dimension separated by a comma. It must also be instantiated with the new operator.
Finally, we have the one dimensional array of string types.
In each case, you can see that array elements are accessed by identifying the integer index for the item you wish to refer to. Arrays sizes can be any int type value. Their indexes begin at 0.

Summary

A variable is an identifier with a type that holds a value of that type. Simple types include the integrals, floating points, decimal, and bool. C# has several mathematical and logical operators that participate in forming expressions. C# also offers the single dimension, multi-dimension and jagged array types.
In this lesson you learned how to write simple statements and code a program that works linearly from start to finish. However, this is not as useful as it can be because you need to be able to make decisions and execute different blocks of code depending on different conditions.

Lesson 3: Control Statements - Selection

In the last couple of lessons, every program you saw contained a limited amount of sequential steps and then stopped. There were no decisions you could make with the input and the only constraint was to follow straight through to the end. The information in this lesson will help you branch into separate logical sequences based on decisions you make. More specifically, the goals of this lesson are as follows:
  • Learn the if statements.
  • Learn the switch statement.
  • Learn how break is used in switch statements.
  • Understand proper use of the goto statement.

The if Statement

An if statement allows you to take different paths of logic, depending on a given condition. When the condition evaluates to a boolean true, a block of code for that true condition will execute. You have the option of a single if statement, multiple else if statements, and an optional else statement. Listing 3-1 shows how each of these types of if statements work.
Listing 3-1. Forms of the if statement: IfSelection.cs
using System;

class IfSelect
{
    public static void Main()
    {
        string myInput;
        int myInt;


        Console.Write("Please enter a number: ");
        myInput = Console.ReadLine();
        myInt = Int32.Parse(myInput);


        // Single Decision and Action with brackets
        if (myInt > 0)
        {
            Console.WriteLine("Your number {0} is greater than zero.", myInt);
        }


        // Single Decision and Action without brackets
        if (myInt < 0)
            Console.WriteLine("Your number {0} is less than zero.", myInt);


        // Either/Or Decision
        if (myInt != 0)
        {
            Console.WriteLine("Your number {0} is not equal to zero.", myInt);
        }
        else
       {
            Console.WriteLine("Your number {0} is equal to zero.", myInt);
        }


        // Multiple Case Decision
        if (myInt < 0 || myInt == 0)
        {
            Console.WriteLine("Your number {0} is less than or equal to zero.", myInt);
        }
        else if (myInt > 0 && myInt <= 10)
        {
            Console.WriteLine("Your number {0} is in the range from 1 to 10.", myInt);
        }
        else if (myInt > 10 && myInt <= 20)
        {
            Console.WriteLine("Your number {0} is in the range from 11 to 20.", myInt);
        }
        else if (myInt > 20 && myInt <= 30)
        {
            Console.WriteLine("Your number {0} is in the range from 21 to 30.", myInt);
        }
        else
       {
            Console.WriteLine("Your number {0} is greater than 30.", myInt);
        }
    }
}

 Get Setup Instructions For How to Run this Program
The statements in Listing 3-1 use the same input variable, myInt as a part of their evaluations. This is another way of obtaining interactive input from the user. Here's the pertinent code:
        Console.Write("Please enter a number: ");
        myInput = Console.ReadLine();
        myInt = Int32.Parse(myInput);

We first print the line "Please enter a number: " to the console. The Console.ReadLine() statement causes the program to wait for input from the user, who types a number and then presses Enter. This number is returned in the form of a string into the myInput variable, which is a string type. Since we must evaluate the user's input in the form of an int, myInput must be converted. This is done with the command Int32.Parse(myInput).  (Int32 and similar types will be covered in another lesson on advanced types) The result is placed into the myInt variable, which is an int type.
Now that we have a variable in the type we wanted, we will evaluate it with if statements. The first statement is of the form if (boolean expression) { statements }, as shown below:
        // Single Decision and Action with brackets
        if (myInt > 0)
        {
            Console.WriteLine("Your number {0} is greater than zero.", myInt);
        }

You must begin with the keyword if. Next is the boolean expression between parenthesis. This boolean expression must evaluate to a true or false value. In this case, we are checking the user's input to see if it is greater than (>) 0. If this expression evaluates to true, we execute the statements within the curly braces. (We refer to the structure with curly braces as a "block") There could be one or more statements within in this block. If the boolean expression evaluates to false, we ignore the statements inside the block and continue program execution with the next statement after the block.
Note: In other languages, such as C and C++, conditions can be evaluated where a result of 0 is false and any other number is true. In C#, the condition must evaluate to a boolean value of either true or false. If you need to simulate a numeric condition with C#, you can do so by writing it as (myInt != 0), which means that the expression evaluate to true if myInt is not 0.
The second if statement is much like the first, except it does not have a block, as shown here:
        // Single Decision and Action without brackets
        if (myInt < 0)
            Console.WriteLine("Your number {0} is less than zero.", myInt);

If its boolean expression evaluates to true, the first statement after the boolean expression will be executed. When the boolean expression evaluates to false, the first statement after the boolean expression will be skipped and the next program statement will be executed. This form of if statement is adequate when you only have a single statement to execute. If you want to execute two or more statements when the boolean expression evaluates to true, you must enclose them in a block.
My personal recommendation is to make it a habit to always put your if statements within a block, regardless of whether or not you have only one statement to execute. This will help avoid mistakes where you later decide to add a statement and forget to add the curly braces.
Most of the time, you'll want to make an either/or kind of decision. This called an if/else statement. The third if statement in Listing 3-1 presents this idea, as shown below:
        // Either/Or Decision
        if (myInt != 0)
        {
            Console.WriteLine("Your number {0} is not equal to zero.", myInt);
        }
        else
       {
            Console.WriteLine("Your number {0} is equal to zero.", myInt);
        }

When the boolean expression evaluates to true, the statement(s) in the block immediately following the if statement are executed. However, when the boolean expression evaluates to false, the statements in the block following the else keyword are executed.
When you have multiple expressions to evaluate, you can use the if/else if/else form of the if statement. We show this form in the fourth if statement of Listing 3-1, and repeated below:
        // Multiple Case Decision
        if (myInt < 0 || myInt == 0)
        {
            Console.WriteLine("Your number {0} is less than or equal to zero.", myInt);
        }
        else if (myInt > 0 && myInt <= 10)
        {
            Console.WriteLine("Your number {0} is in the range from 1 to 10.", myInt);
        }
        else if (myInt > 10 && myInt <= 20)
        {
            Console.WriteLine("Your number {0} is in the range from 11 to 20.", myInt);
        }
        else if (myInt > 20 && myInt <= 30)
        {
            Console.WriteLine("Your number {0} is in the range from 21 to 30.", myInt);
        }
        else
       {
            Console.WriteLine("Your number {0} is greater than 30.", myInt);
        }

This example begins with the if keyword, again executing the following block if the boolean expression evaluates to true. However, this time you can evaluate multiple subsequent conditions with the else if keyword combination. the else if statement also takes a boolean expression, just like the if statement. The rules are the same, when the boolean expression for the else if statement evaluates to true, the block immediately following the boolean expression is executed. This can go on until all cases have been evaluated, but the entire if/else if sequence must end with a final else part. When none of the other if or else if boolean expressions evaluate to true, the block following the else keyword will be executed. Only one section of an if/else if/else statement will be executed.
One difference in the last statement from the others is the boolean expressions. The boolean expression, (myInt < 0 || myInt == 0), contains the conditional OR (||) operator. In both the regular OR (|) operator and the conditional OR (||) operator, the boolean expression will evaluate to true if either of the two sub-expressions on either side of the operator evaluate to true. The primary difference between the two OR forms are that the regular OR operator will evaluate both sub-expressions every time. However, the conditional OR will evaluate the second sub-expression only if the first sub-expression evaluates to false.
The boolean expression, (myInt > 0 && myInt <= 10), contains the conditional AND operator.  Both the regular AND (&) operator and the conditional AND (&&) operator will return true when both of the sub-expressions on either side of the operator evaluate to true.  The difference between the two is that the regular AND operator will evaluate both expressions every time. However, the conditional AND operator will evaluate the second sub-expression only when the first sub-expression evaluates to true.
The conditional operators (&& and ||) are commonly called short-circuit operators because they do not always evaluate the entire expression. Thus, they are also used to produce more efficient code by ignoring unnecessary logic.

The Switch Statement

Another form of selection statement is the switch statement, which executes a set of logic depending on the value of a given parameter. The types of the values a switch statement operates on can be booleans, enums, integral types, and strings. Lesson 2: Operators, Types, and Variables discussed the bool type, integral types and strings and Lesson 17: Enums will teach you what an enum type is. Listing 3-2 shows how to use the switch statement with both int and string types.
Listing 3-2. Switch Statements: SwitchSelection.cs
using System;

class SwitchSelect
{
    public static void Main()
    {
        string myInput;
        int myInt;

        begin:

        Console.Write("Please enter a number between 1 and 3: ");
        myInput = Console.ReadLine();
        myInt = Int32.Parse(myInput);

        // switch with integer type
        switch (myInt)
        {
            case 1:
                Console.WriteLine("Your number is {0}.", myInt);
                break;
            case 2:
                Console.WriteLine("Your number is {0}.", myInt);
                break;
            case 3:
                Console.WriteLine("Your number is {0}.", myInt);
                break;
            default:
                Console.WriteLine("Your number {0} is not between 1 and 3.", myInt);
                break;
        }

        decide:

        Console.Write("Type \"continue\" to go on or \"quit\" to stop: ");
        myInput = Console.ReadLine();

        // switch with string type
        switch (myInput)
        {
            case "continue":
                goto begin;
            case "quit":
                Console.WriteLine("Bye.");
                break;
            default:
                Console.WriteLine("Your input {0} is incorrect.", myInput);
                goto decide;
        }
    }

}
Get Setup Instructions For How to Run this Program
Listing 3-2 shows a couple of switch statements. The switch statement begins with the switch keyword followed by the switch expression. In the first switch statement in listing 3-2, the switch expression evaluates to an int type, as follows:
        // switch with integer type
        switch (myInt)
        {
            case 1:
                Console.WriteLine("Your number is {0}.", myInt);
                break;
            case 2:
                Console.WriteLine("Your number is {0}.", myInt);
                break;
            case 3:
                Console.WriteLine("Your number is {0}.", myInt);
                break;
            default:
                Console.WriteLine("Your number {0} is not between 1 and 3.", myInt);
                break;
        }

The switch block follows the switch expression, where one or more choices are evaluated for a possible match with the switch expression. Each choice is labeled with the case keyword, followed by an example that is of the same type as the switch expression and followed by a colon (:). In the example we have case 1:, case 2:, and case 3:. When the result evaluated in the switch expression matches one of these choices, the statements immediately following the matching choice are executed, up to and including a branching statement, which could be either a break, continue, goto , return, or throw statement. Table 3-1 summarizes the branching statements.
Table 3-1. C# Branching Statements
Branching statement
Description
break
Leaves the switch block
continue
Leaves the switch block, skips remaining logic in enclosing loop, and goes back to loop condition to determine if loop should be executed again from the beginning. Works only if switch statement is in a loop as described in Lesson 04: Control Statements - Loops.
goto
Leaves the switch block and jumps directly to a label of the form ":"
return
Leaves the current method. Methods are described in more detail in Lesson 05: Methods.
throw
Throws an exception, as discussed in Lesson 15: Introduction to Exception Handling.
You may also include a default choice following all other choices. If none of the other choices match, then the default choice is taken and its statements are executed. Although use of the default label is optional, I highly recommend that you always include it. This will help catch unforeseen circumstances and make your programs more reliable.
Each case label must end with a branching statement, as described in Table 3-1, which is normally the break statement. The break statement will cause the program to exit the switch statement and begin execution with the next statement after the switch block. There are two exceptions to this: adjacent case statements with no code in between or using a goto statement. Here's an example that shows how to combine case statements:
        switch (myInt)
        {
            case 1:
            case 2:
            case 3:
                Console.WriteLine("Your number is {0}.", myInt);
                break;
            default:
                Console.WriteLine("Your number {0} is not between 1 and 3.", myInt);
                break;
        }

By placing case statements together, with no code in-between, you create a single case for multiple values. A case without any code will automatically fall through to the next case. The example above shows how the three cases for myInt equal to 1, 2, or 3, where case 1 and case 2 will fall through and execute code for case 3.
Another way to control the flow of logic in a switch statement is by using the goto statement. You can either jump to another case statement, or jump out of the switch statement. The second switch statement in Listing 3-2 shows the use of the goto statement, as shown below:
        // switch with string type
        switch (myInput)
        {
            case "continue":
                goto begin;
            case "quit":
                Console.WriteLine("Bye.");
                break;
            default:
                Console.WriteLine("Your input {0} is incorrect.", myInput);
                goto decide;
        }

Note: in the current example, "continue", is a case of the switch statement -- not the keyword.
The goto statement causes program execution to jump to the label following the goto keyword. During execution, if the user types in "continue", the switch statement matches this input (a string type) with the case "continue": label and executes the "goto begin:" instruction. The program will then leave the switch statement and start executing the first program statement following the begin: label. This is effectively a loop, allowing you to execute the same code multiple times. The loop will end when the user types the string "quit". This will be evaluated with the case "quit": choice, which will print "Bye." to the console, break out of the switch statement and end the program.
Warning: Don't create loops like this. It is *bad* programming style. The only reason it is here is because I wanted to show you the syntax of the goto statement. Instead, use one of the structured looping statements, described in Lesson 04: Control Statements - Loops.
When neither the "continue" nor "quit" strings are entered, the "default:" case will be entered. It will print an error message to the console and then execute the goto decide: command. This will cause program execution to jump to the first statement following the decide: label, which will ask the user if they want to continue or quit. This is effectively another loop.
Clearly, the goto statement is powerful and can, under controlled circumstances, be useful. However, I must caution you strongly on its use. The goto statement has great potential for misuse. You could possibly create a very difficult program to debug and maintain. Imagine the spaghetti code that could be created by random goto statements throughout a program. In the next lesson, I'll show you a better way to create loops in your program.

Summary

The if statement can be written in multiple ways to implement different branches of logic. The switch statement allows a choice among a set of bool, enum, integral, or string types. You use break, continue, goto, return, or throw statements to leave a case statement. Be sure to avoid the goto statement in your code unless you have an extremely good reason for using it.
In addition to branching based on a condition, it is useful to be able to execute a block of statements multiple times. A goto statement is not proper or adequate for such logic. Therefore, I invite you to return for Lesson 4: Control Statements - Loops. This will be a continuation of the same topic.

Lesson 4: Control Statements - Loops

In the last lesson, you learned how to create a simple loop by using the goto statement. I advised you that this is not the best way to perform loops in C#. The information in this lesson will teach you the proper way to execute iterative logic with the various C# looping statements. Its goal is to meet the following objectives:
  • Learn the while loop.
  • Learn the do loop.
  • Learn the for loop.
  • Learn the foreach loop.
  • Complete your knowledge of the break statement.
  • Teach you how to use the continue statement.

The while Loop

A while loop will check a condition and then continues to execute a block of code as long as the condition evaluates to a boolean value of true. Its syntax is as follows: while () { }. The statements can be any valid C# statements. The boolean expression is evaluated before any code in the following block has executed. When the boolean expression evaluates to true, the statements will execute. Once the statements have executed, control returns to the beginning of the while loop to check the boolean expression again.
When the boolean expression evaluates to false, the while loop statements are skipped and execution begins after the closing brace of that block of code. Before entering the loop, ensure that variables evaluated in the loop condition are set to an initial state. During execution, make sure you update variables associated with the boolean expression so that the loop will end when you want it to. Listing 4-1 shows how to implement a while loop.
Listing 4-1. The While Loop: WhileLoop.cs
using System;

class WhileLoop
{
    public static void Main()
    {
        int myInt = 0;

        while (myInt < 10)
        {
            Console.Write("{0} ", myInt);
            myInt++;
        }
        Console.WriteLine();
    }
}

Listing 4-1 shows a simple while loop. It begins with the keyword while, followed by a boolean expression. All control statements use boolean expressions as their condition for entering/continuing the loop. This means that the expression must evaluate to either a true or false value. In this case we are checking the myInt variable to see if it is less than (<) 10. Since myInt was initialized to 0, the boolean expression will return true the first time it is evaluated. When the boolean expression evaluates to true, the block immediately following the boolean expression will be executed.
Within the while block we print the number and a space to the console. Then we increment (++) myInt to the next integer. Once the statements in the while block have executed, the boolean expression is evaluated again. This sequence will continue until the boolean expression evaluates to false. Once the boolean expression is evaluated as false, program control will jump to the first statement following the while block. In this case, we will write the numbers 0 through 9 to the console, exit the while block, and print a new line to the console.

The do Loop

A do loop is similar to the while loop, except that it checks its condition at the end of the loop. This means that the do loop is guaranteed to execute at least one time. On the other hand, a while loop evaluates its boolean expression at the beginning and there is generally no guarantee that the statements inside the loop will be executed, unless you program the code to explicitly do so. One reason you may want to use a do loop instead of a while loop is to present a message or menu such as the one in Listing 4-2 and then retrieve input from a user.
Listing 4-2. The Do Loop: DoLoop.cs
using System;

class DoLoop
{
    public static void Main()
    {
        string myChoice;

        do

       {
            // Print A Menu
            Console.WriteLine("My Address Book\n");

            Console.WriteLine("A - Add New Address");
            Console.WriteLine("D - Delete Address");
            Console.WriteLine("M - Modify Address");
            Console.WriteLine("V - View Addresses");
            Console.WriteLine("Q - Quit\n");

            Console.WriteLine("Choice (A,D,M,V,or Q): ");

            // Retrieve the user's choice
            myChoice = Console.ReadLine();

            // Make a decision based on the user's choice
            switch(myChoice)
            {
                case "A":
                case "a":
                    Console.WriteLine("You wish to add an address.");
                    break;
                case "D":
                case "d":
                    Console.WriteLine("You wish to delete an address.");
                    break;
                case "M":
                case "m":
                    Console.WriteLine("You wish to modify an address.");
                    break;
                case "V":
                case "v":
                    Console.WriteLine("You wish to view the address list.");
                    break;
                case "Q":
                case "q":
                    Console.WriteLine("Bye.");
                    break;
                default:
                    Console.WriteLine("{0} is not a valid choice", myChoice);
                    break;
            }

            // Pause to allow the user to see the results
            Console.Write("Press Enter key to continue...");
            Console.ReadLine();
            Console.WriteLine();
        } while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
    }
}

Listing 4-2 shows a do loop in action. The syntax of the do loop is do { } while ();. The statements can be any valid C# programming statements you like. The boolean expression is the same as all others we've encountered so far. It returns either true or false.
In the Main() method, we declare the variable myChoice of type string. Then we print a series of statement to the console. This is a menu of choices for the user. We must get input from the user, which is in the form of a Console.ReadLine() method which returns the user's value into the myChoice variable. We must take the user's input and process it. A very efficient way to do this is with a switch statement. Notice that we've placed matching upper and lower case letters together to obtain the same functionality. This is the only legal way to have automatic fall through between cases. If you were to place any statements between two cases, you would not be able to fall through. Another point is that we used the default: case, which is a very good habit for the reasons stated in Lesson 3: Control Statements - Selection.

The for Loop

A for loop works like a while loop, except that the syntax of the for loop includes initialization and condition modification. for loops are good for when you know exactly how many times you want to perform the statements within the loop. The contents within the for loop parenthesis holds three sections separated by semicolons (; ; ) { }.
The initializer list is a comma separated list of expressions. These expressions are evaluated only once during the lifetime of the for loop. This is a one-time operation, before loop execution. This section is commonly used to initialize an integer to be used as a counter.
Once the initializer list has been evaluated, the for loop gives control to its second section, the boolean expression. There is only one boolean expression, but it can be as complicated as you like as long as the result evaluates to true or false. The boolean expression is commonly used to verify the status of a counter variable.
When the boolean expression evaluates to true, the statements within the curly braces of the for loop are executed. After executing for loop statements, control moves to the top of loop and executes the iterator list, which is normally used to increment or decrement a counter. The iterator list can contain a comma separated list of statements, but is generally only one statement. Listing 4-3 shows how to implement a for loop.
Listing 4-3. The For Loop: ForLoop.cs
using System;

class ForLoop
{
    public static void Main()
    {
        for (int i=0; i < 20; i++)
        {
            if (i == 10)
                break;

            if (i % 2 == 0)
                continue;

            Console.Write("{0} ", i);
        }
        Console.WriteLine();
    }
}

Normally, for loop statements execute from the opening curly brace to the closing curly brace without interruption. However, in Listing 4-3, we've made a couple exceptions. There are a couple if statements disrupting the flow of control within the for block.
The first if statement checks to see if i is equal to 10. Now you see another use of the break statement. Its behavior is similar to the selection statements, as discussed in Lesson 3: Control Statements - Selection. It simply breaks out of the loop at that point and transfers control to the first statement following the end of the for block.
The second if statement uses the remainder operator to see if i is a multiple of 2. This will evaluate to true when i is divided by 2 with a remainder equal to zero, (0). When true, the continue statement is executed, causing control to skip over the remaining statements in the loop and transfer back to the iterator list. By arranging the statements within a block properly, you can conditionally execute them based upon whatever condition you need.
When program control reaches either a continue statement or end of block, it transfers to the third section within the for loop parentheses, the iterator list. This is a comma separated list of actions that are executed after the statements in the for block have been executed. Listing 4-3 is a typical action, incrementing the counter. Once this is complete, control transfers to the boolean expression for evaluation.
Similar to the while loop, a for loop will continue as long as the boolean expression is true. When the boolean expression becomes false, control is transferred to the first statement following the for block.
For this tutorial, I chose to implement break and continue statements in Listing 4-3 only. However, they may be used in any of the loop statements.

The foreach Loop

A foreach loop is used to iterate through the items in a list. It operates on arrays or collections such as ArrayList, which can be found in the System.Collections namespace. The syntax of a foreach loop is foreach ( in ) { }. The type is the type of item contained in the list. For example, if the type of the list was int[] then the type would be int.
The item name is an identifier that you choose, which could be anything but should be meaningful. For example, if the list contained an array of people's ages, then a meaningful name for item name would be age.
The in keyword is required.
As mentioned earlier, the list could be either an array or a collection, as defined by types found in the System.Collections namespace. You learned about arrays in Lesson 02: Operators, Types, and Variables. If you aren't familiar with collections, open the .NET Framework SDK documentation and look for the System.Collections namespace to see what types are available.
While iterating through the items of a list with a foreach loop, the list is read-only. This means that you can't change the value of any items in the list within a foreach loop.
On each iteration through a foreach loop the list is queried for a new value. As long as the list can return a value, this value will be put into the read-only item name variable, causing the statements in the foreach block to be executed. When the collection has been fully traversed, control will transfer to the first executable statement following the end of the foreach block. Listing 4-4 demonstrates how to use a foreach loop.
Listing 4-4. The ForEach Loop: ForEachLoop.cs
using System;

class ForEachLoop
{
    public static void Main()
    {
        string[] names = {"Cheryl", "Joe", "Matt", "Robert"};

        foreach
(string person in names)
        {
            Console.WriteLine("{0} ", person);
        }
    }
}

In Listing 4-4, the first thing we've done inside the Main() method is declare and initialize the names array with 4 strings. This is the list used in the foreachloop.
In the foreach loop, we've used a string variable named "person", as the item name, to hold each element of the names array. As long as there are names in the array that have not been returned, we will use the Console.WriteLine() method to print each value of the person variable to the screen.

Summary

Loops allow you to execute a block of statements repeatedly. C# offers several statements to construct loops with, including the while, doWhile, for, and foreach loops. while loops execute a block of statements as long as an expression is true, do loops execute a block of statements at least once and then keep going as long as a condition is true, for loops execute a block of statements a specified amount of times, and foreach loops execute a block of statements for each item in a collection. Normally a block of statements will execute from beginning to end. However, the normal flow of a loop can be changed with the break and continue statements.
So far, the only method you've seen in this tutorial is the Main method, which is the entry point of a C# application. However, you are probably wanting to write larger programs to test your new knowledge. This requires breaking up the code into methods to keep it organized and logical. For this, I invite you to return for Lesson 5:  Introduction to Methods, where you can learn new techniques of organizing your code.

Lesson 5: Methods

In previous lessons of this tutorial, all of our functionality for each program resided in the Main() method.  While this was adequate for the simple programs we used to learn earlier concepts, there is a better way to organize your program, using methods. A method helps you separate your code into modules that perform a given task.  The objectives of this lesson are as follows:
  • Understand the structure of a method.
  • Know the difference between static and instance methods.
  • Learn to instantiate objects.
  • Learn how to call methods of an instantiated object.
  • Understand the 4 types of parameters.
  • Learn how to use the this reference.

Method Structure

Methods are extremely useful because they allow you to separate your logic into different units. You can pass information to methods, have it perform one or more statements, and retrieve a return value. The capability to pass parameters and return values is optional and depends on what you want the method to do. Here's a description of the syntax required for creating a method:
    attributes modifiers return-type method-name( parameters ) { statements }
We defer discussion of attributes and modifiers to a later lesson.  The return-type can be any C# type.  It can be assigned to a variable for use later in the program.  The method name is a unique identifier for what you wish to call a method.  To promote understanding of your code, a method name should be meaningful and associated with the task the method performs.  Parameters allow you to pass information to and from a method.  They are surrounded by parenthesis.  Statements within the curly braces carry out the functionality of the method.
Listing 5-1.  One Simple Method:  OneMethod.cs
using System;

class OneMethod
{
    public static void Main()
    {
        string myChoice;

        OneMethod om = new OneMethod();

        do

       {
            myChoice = om.getChoice();

            // Make a decision based on the user's choice
            switch(myChoice)
            {
                case "A":
                case "a":
                    Console.WriteLine("You wish to add an address.");
                    break;
                case "D":
                case "d":
                    Console.WriteLine("You wish to delete an address.");
                    break;
                case "M":
                case "m":
                    Console.WriteLine("You wish to modify an address.");
                    break;
                case "V":
                case "v":
                    Console.WriteLine("You wish to view the address list.");
                    break;
                case "Q":
                case "q":
                    Console.WriteLine("Bye.");
                    break;
                default:
                    Console.WriteLine("{0} is not a valid choice", myChoice);
                    break;
            }

            // Pause to allow the user to see the results
            Console.WriteLine();
            Console.Write("Press Enter key to continue...");

            Console.ReadLine();
            Console.WriteLine();

        } while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
    }

    string
getChoice()
    {
        string myChoice;

        // Print A Menu
        Console.WriteLine("My Address Book\n");

        Console.WriteLine("A - Add New Address");
        Console.WriteLine("D - Delete Address");
        Console.WriteLine("M - Modify Address");
        Console.WriteLine("V - View Addresses");
        Console.WriteLine("Q - Quit\n");

        Console.Write("Choice (A,D,M,V,or Q): ");

        // Retrieve the user's choice
        myChoice = Console.ReadLine();
        Console.WriteLine();

        return
myChoice;
    }
}

The program in Listing 5-1 is similar to the DoLoop program from Lesson 4, except for one difference.  Instead of printing the menu and accepting input in the Main() method, this functionality has been moved to a new method called getChoice().  The return type is a string.  This string is used in the switch statement in Main().  The method name "getChoice" describes what happens when it is invoked.  Since the parenthesis are empty, no information will be transferred to or from the getChoice() method.
Within the method block we first declare the variable myChoice.  Although this is the same name and type as the myChoice variable in Main(), they are both unique variables.  They are local variables and they are visible only in the block they are declared.  In other words, the myChoice in getChoice() knows nothing about the existence of the myChoice in Main(), and vice versa.
The getChoice() method prints a menu to the console and gets the user's input.  The return statement sends the data from the myChoice variable back to the caller, Main(), of getChoice().  Notice that the type returned by the return statement must be the same as the return-type in the function declaration.  In this case it is a string.
In the Main() method we must instantiate a new OneMethod object before we can use getChoice().  This is because of the way getChoice() is declared.  Since we did not specify a static modifier, as for Main(), getChoice() becomes an instance method.  The difference between instance methods and static methods is that multiple instances of a class can be created (or instantiated) and each instance has its own separate getChoice() method.  However, when a method is static, there are no instances of that method, and you can invoke only that one definition of the static method.
So, as stated, getChoice() is not static and therefore, we must instantiate a new object to use it.  This is done with the declaration OneMethod om = new OneMethod().  On the left hand side of the declaration is the object reference om which is of type OneMethod.  The distinction of om being a reference is important.  It is not an object itself, but it is a variable that can refer (or point ) to an object of type OneMethod.  On the right hand side of the declaration is an assignment of a new OneMethod object to the reference om.  The keyword new is a C# operator that creates a new instance of an object on the heap.  What is happening here is that a new OneMethod instance is being created on the heap and then being assigned to the om reference.  Now that we have an instance of the OneMethod object referenced by om, we can manipulate that instance through the om reference.
Methods, fields, and other class members can be accessed, identified, or manipulated through the "." (dot) operator.  Since we want to call getChoice(), we do so by using the dot operator through the om reference:  om.getChoice().  The program then executes the statements in the getChoice() block and returns.  To capture the value getChoice() returns, we use the "=" (assignment) operator.  The returned string is placed into Main()'s local myChoice variable.  From there, the rest of the program executes as expected, using concepts from earlier lessons.
Listing 5-2. Method Parameters:  MethodParams.cs
using System;

class Address
{
    public string name;
    public
string address;
}

class
MethodParams
{
    public static void Main()
    {
        string myChoice;

        MethodParams mp = new MethodParams();

        do

       {
            // show menu and get input from user
            myChoice = mp.getChoice();

            // Make a decision based on the user's choice
            mp.makeDecision(myChoice);

            // Pause to allow the user to see the results
            Console.Write("Press Enter key to continue...");
            Console.ReadLine();
            Console.WriteLine();
        } while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
    }

    // show menu and get user's choice
    string getChoice()
    {
        string myChoice;

        // Print A Menu
        Console.WriteLine("My Address Book\n");

        Console.WriteLine("A - Add New Address");
        Console.WriteLine("D - Delete Address");
        Console.WriteLine("M - Modify Address");
        Console.WriteLine("V - View Addresses");
        Console.WriteLine("Q - Quit\n");

        Console.WriteLine("Choice (A,D,M,V,or Q): ");

        // Retrieve the user's choice
        myChoice = Console.ReadLine();

        return
myChoice;
    }

    // make decision
    void makeDecision(string myChoice)
    {
        Address addr = new Address();

        switch
(myChoice)
        {
            case "A":
            case "a":
                addr.name = "Joe";
                addr.address = "C# Station";
                this.addAddress(ref addr);
                break;
            case "D":
            case "d":
                addr.name = "Robert";
                this.deleteAddress(addr.name);
                break;
            case "M":
            case "m":
                addr.name = "Matt";
                this.modifyAddress(out addr);
                Console.WriteLine("Name is now {0}.", addr.name);
                break;
            case "V":
            case "v":
                this.viewAddresses("Cheryl", "Joe", "Matt", "Robert");
                break;
            case "Q":
            case "q":
                Console.WriteLine("Bye.");
                break;
            default:
                Console.WriteLine("{0} is not a valid choice", myChoice);
                break;
        }
    }

    // insert an address
    void addAddress(ref Address addr)
    {
        Console.WriteLine("Name: {0}, Address: {1} added.", addr.name, addr.address);
    }

    // remove an address
    void deleteAddress(string name)
    {
        Console.WriteLine("You wish to delete {0}'s address.", name);
    }

    // change an address
    void modifyAddress(out Address addr)
    {
        //Console.WriteLine("Name: {0}.", addr.name); // causes error!
        addr = new Address();
        addr.name = "Joe";
        addr.address = "C# Station";
    }

    // show addresses
    void viewAddresses(params string[] names)
    {
        foreach (string name in names)
        {
            Console.WriteLine("Name: {0}", name);
        }
    }
}

Listing 5-2 is a modification of Listing 5-1, modularizing the program and adding more implementation to show parameter passing.  There are 4 kinds of parameters a C# method can handle:  out, ref, params, and value.  To help illustrate usage of parameters, we created an Address class with two string fields.
In Main() we call getChoice() to get the user's input and put that string in the myChoice variable.  Then we use myChoice as an argument to makeDecision().  In the declaration of makeDecision() you'll notice its one parameter is declared as a string with the name myChoice.  Again, this is a new myChoice, separate from the caller's argument and local only to this method.  Since makeDecision()'s myChoice parameter does not have any other modifiers, it is considered a value parameter.  The actual value of the argument is copied on the stack.  Variables given by value parameters are local and any changes to that local variable do not affect the value of the variable used in the caller's argument. 
The switch statement in makeDecision() calls a method for each case.  These method calls are different from the ones we used in Main().  Instead of using the mp reference, they use the this keyword.  this is a reference to the current object.  We know the current object has been instantiated because makeDecision() is not a static method.  Therefore, we can use the this reference to call methods within the same instance.
The addAddress() method takes a ref parameter.  This means that a reference to the parameter is copied to the method.  This reference still refers to the same object on the heap as the original reference used in the caller's argument.  This means any changes to the local reference's object also changes the caller reference's object.  The code can't change the reference, but it can make changes to the object being referenced.  You can think of this as a way to have an input/output parameter. 
I've tried to simplify things to minimize confusion.  If you're interested in method parameter semantics in greater depth, check out Jon Skeet's article on Parameter Passing in C#.  However, you may want to read a few more of these lessons first because his discussion is much more advanced than the place this lesson is in the tutorial.
out parameters are for those parameters that are only returned from a method.  This is more efficient because the program doesn't have the overhead of copying the parameter in to the method.  On a normal program, this overhead is minimal.  However, in distributed processing scenarios, where network communication is the bottleneck, out parameters make a larger difference. 
modifyAddress() has an out parameter.  out parameters are only passed back to the calling function.  Because of definite assignment rules, you cannot use this variable until it has a valid value assigned.  The first line in modifyAddress() is commented on purpose to illustrate this point.  Uncomment it and compile to see what happens.  Once assigned and the program returns, the value of the out parameter will be copied into the caller's argument variable.  You must assign a value to an out parameter before your method returns.
A very useful addition to the C# language is the params parameter, which lets you define a method that can accept a variable number of arguments.  The params parameter must be a single dimension or jagged array.  In makeDecision() we pass in four comma delimited string arguments.  The number of arguments is variable.  In viewAddresses() we use a foreach loop to print each of these strings.  Instead of the comma delimited list, the input could have also been a string array.  The params parameter is considered an input only parameter and any changes affect the local copy only.
In summary, you understand the structure of a method.  The four types of paramters are value, ref, out, and params.  When you wish to use an instance method, you must instantiate its object as opposed to static methods that can be called any time.  The this reference refers to its containing object and may be used to refer to its containing object's members, including methods.

Lesson 6: Namespaces

This lesson introduces you to C# Namespaces.  Our objectives are as follows:
  • Understand what Namespace is.
  • Learn how to implement the using directive.
  • Learn to use alias directive.
  • Understand what are namespace members.
In Lesson 1, you saw the using System; directive in the SimpleHello program.  This directive allowed you to use members of the System namespace.  Because of the narrow focus of that lesson, we needed to delay explanation until now.  When you've completed this lesson you will understand the using directive and more.
Namespaces are C# program elements designed to help you organize your programs.  They also provide assistance in avoiding name clashes between two sets of code.  Implementing Namespaces in your own code is a good habit because it is likely to save you from problems later when you want to reuse some of your code.
Namespaces don't correspond to file or directory names.  If naming directories and files to correspond to namespaces helps you organize your code, then you may do so, but it is not required.
Listing 6-1.  The C# Station Namespace:  NamespaceCSS.cs
// Namespace Declaration
using
System;

// The C# Station Namespace
namespace
csharp_station
{
    // Program start class
    class NamespaceCSS
    {
        // Main begins program execution.
        public static void Main()
        {
            // Write to console
            Console.WriteLine("This is the new C# Station Namespace.");
        }
    }
}

Listing 6-1 shows how to create a namespace.  We declare the new namespace by putting the word namespace in front of csharp_station.  Curly braces surround the members inside the csharp_station namespace.
Listing 6-2. Nested Namespace 1:  NestedNamespace1.cs
// Namespace Declaration
using System;

// The C# Station Tutorial Namespace
namespace csharp_station
{
    namespace tutorial
    {
        // Program start class
        class NamespaceCSS
        {
            // Main begins program execution.
            public static void Main()
            {
                // Write to console
                Console.WriteLine("This is the new C# Station Tutorial Namespace.");
            }
        }
    }
}

Namespaces allow you to create a system to organize your code.  A good way to organize your namespaces is via a hierarchical system.  You put the more general names at the top of the hierarchy and get more specific as you go down.  This hierarchical system can be represented by nested namespaces.  Listing 6-2 shows how to create a nested namespace.  By placing code in different sub-namespaces, you can keep your code organized. 
Listing 6-3. Nested Namespace 2:  NestedNamespace2.cs
// Namespace Declaration
using System;

// The C# Station Tutorial Namespace
namespace csharp_station.tutorial
{
    // Program start class
    class NamespaceCSS
    {
        // Main begins program execution.
        public static void Main()
        {
            // Write to console
            Console.WriteLine("This is the new C# Station Tutorial Namespace.");
        }
    }
}

Listing 6-3 shows another way of writing nested namespaces.  It specifies the nested namespace with the dot operator between csharp_station and tutorial.  The result is exactly the same as Listing 6-2.  However, Listing 6-3 is easier to write. 
Listing 6-4. Calling Namespace Members:  NamespaceCall.cs
// Namespace Declaration
using System;

namespace csharp_station
{
    // nested namespace
    namespace tutorial
    {
        class myExample1
        {
            public static void myPrint1()
            {
                Console.WriteLine("First Example of calling another namespace member.");
            }
        }
    }

    // Program start class
    class NamespaceCalling
    {
        // Main begins program execution.
        public static void Main()
        {
            // Write to console
            tutorial.myExample1.myPrint1();
            tutorial.myExample2.myPrint2();
        }
    }
}

// same namespace as nested namespace above
namespace csharp_station.tutorial
{
    class myExample2
    {
        public static void myPrint2()
        {
            Console.WriteLine("Second Example of calling another namespace member.");
        }
    }
}

Listing 6-4 provides an example of how to call namespace members with fully qualified names.  A fully qualified name contains every language element from the namespace name down to the method call.  At the top of the listing there is a nested namespace tutorial within the csharp-station namespace with class myExample1 and method myPrint1Main() calls this method with the fully qualified name of tutorial.myExample1.myPrint().  Since Main() and the tutorial namespace are located in the same namespace, using csharp_station in the fully qualified name is unnecessary.
At the bottom of Listing 6-4 is an addition to the csharp_station.tutorial namespace.  The classes myExample1 and myExample2 both belong to the same namespace.  Additionally, they could be written in separate files and still belong to the same namespace.  In Main(), the myPrint2() method is called with the fully qualified name tutorial.myExample2.myPrint2().  Although the class myExample2 is outside the bounding braces of where the method myPrint2 is called, the namespace csharp_station does not need to be a part of the fully qualified name.  This is because both classes belong to the same namespace, csharp_station.
Notice that I used different names for the two classes myExample1 and myExample2.  This was necessary because every namespace member of the same type must have a unique name.  Remember, they are both in the same namespace and you wouldn't want any ambiguity about which class to use.  The methods myPrint1() and myPrint2() have different names only because it would make the lesson a little easier to follow.  They could have had the same name with no effect, because their classes are different, thus avoiding any ambiguity.
Listing 6-5.  The using Directive:  UsingDirective.cs
// Namespace Declaration
using System;
using csharp_station.tutorial;

// Program start class
class UsingDirective
{
    // Main begins program execution.
    public static void Main()
    {
        // Call namespace member
        myExample.myPrint();
    }
}

// C# Station Tutorial Namespace
namespace csharp_station.tutorial
{
    class myExample
    {
        public static void myPrint()
        {
            Console.WriteLine("Example of using a using directive.");
        }
    }
}

If you would like to call methods without typing their fully qualified name, you can implement the using directive.  In Listing 6-5, we show two using directives.  The first, using System, is the same using directive you have seen in every program in this tutorial.  It allows you to type the method names of members of the System namespace without typing the word System every time.  In myPrint(), Console is a class member of the System namespace with the method WriteLine().  Its fully qualified name is System.Console.WriteLine(...).
Similarly, the using directive using csharp_station.tutorial allows us to implement members of the csharp_station.tutorial namespace without typing the fully qualified name.  This is why we can type myExample.myPrint().  Without the using directive, we would have to type csharp_station.tutorial.myExample.myPrint() every time we wanted to implement that method.
Listing 6-6.  The Alias Directive:  AliasDirective.cs
// Namespace Declaration
using System;
using csTut = csharp_station.tutorial.myExample; // alias

// Program start class
class AliasDirective
{
    // Main begins program execution.
    public static void Main()
    {
        // Call namespace member
        csTut.myPrint();
        myPrint();
    }

    // Potentially ambiguous method.
    static void myPrint()
    {
        Console.WriteLine("Not a member of csharp_station.tutorial.myExample.");
    }
}

// C# Station Tutorial Namespace
namespace csharp_station.tutorial
{
    class myExample
    {
        public static void myPrint()
        {
            Console.WriteLine("This is a member of csharp_station.tutorial.myExample.");
        }
    }
}

Sometimes you may encounter a long namespace and wish to have it shorter.  This could improve readability and still avoid name clashes with similarly named methods.  Listing 6-6 shows how to create an alias with the alias directive using csTut = csharp_station.tutorial.myExample.  Now the expression csTut can be used anywhere, in this file, in place of csharp_station.tutorial.myExample.  We use it in Main().
Also in Main() is a call to the myPrint() method of the AliasDirective class .  This is the same name as the myPrint() method in the myExample class .  The reason both of these methods can be called in the same method call is because the myPrint() method in the myExample class is qualified with the csTut alias.  This lets the compiler know exactly which method is to be executed.  Had we mistakenly omitted csTut from the method call, the compiler would have set up the myPrint() method of the AliasDirective class to run twice.
So far, all we've shown in our namespaces are classes.  However, namespaces can hold other types as follows:
bullet
Classes
bullet
Structures
bullet
Interfaces
bullet
Enumerations
bullet
Delegates
Future chapters we will cover what these types are in more detail.
In summary, you know what a namespace is and you can declare your own namespaces.  If you don't want to type a fully qualified name, you know how to implement the using directive.  When you want to shorten a long namespace declaration, you can use the alias directive.  Also, you have been introduced to some of the other namespace members in addition to the class type.

Lesson 7: Introduction to Classes

This lesson introduces you to C# Classes.  Our objectives are as follows:
  • Implement Constructors.
  • Know the difference between instance and static members.
  • Understand Destructors.
  • Familiarization with Class Members.
Since the beginning of this tutorial, you have been using classes.  By now, you should have a sense of what a class is for and how to specify one.  This lesson will build upon what you already know and introduce the various class members.
Classes are declared by using the keyword class followed by the class name and a set of class members surrounded by curly braces.  Every class has a constructor, which is called automatically any time an instance of a class is created.  The purpose of constructors is to initialize class members when the class is created.  Constructors do not have return values and always have the same name as the class.  Listing 7-1 is an example of a class.
Listing 7-1.  Example C# Classes:  Classes.cs
// Namespace Declaration
using System;

// helper class
class OutputClass
{
    string myString;

    // Constructor
    public OutputClass(string inputString)
    {
        myString = inputString;
    }

    // Instance Method
    public void printString()
    {
        Console.WriteLine("{0}", myString);
    }

    // Destructor
    ~OutputClass()
    {
        // Some resource cleanup routines
    }
}

// Program start class
class ExampleClass
{
    // Main begins program execution.
    public static void Main()
    {
        // Instance of OutputClass
        OutputClass outCl = new OutputClass("This is printed by the output class.");

        // Call Output class' method
        outCl.printString();
    }
}

Listing 7-1 shows two classes.  The top class, OutputClass, has a constructor, instance method, and a destructor.  It also had a field named myString.  Notice how the OutputClass constructor is used to initialize data members of the class.  In this case, the OutputClass constructor accepts a string argument, inputString.  This string is copied to the class field myString.

Constructors are not mandatory, as indicated by the implementation of ExampleClass.  In this case, a default constructor is provided.  A default constructor is simply a constructor with no arguments.  However, a constructor with no arguments is not always useful.  To make default constructors more useful, you can implement them with initializers.  Here is an example:
    public OutputClass() : this("Default Constructor String") { }
Imagine this constructor was included in class OutputClass from Listing 7-1.  This default constructor is followed by an initializer.  The colon, ":", marks the beginning of the initializer, followed by the this keyword.  The this keyword refers to this particular object.  It effectively makes a call to the constructor of the same object it is defined in.  After the this keyword is a parameter list with a string.  The action taken by the initializer above is to invoke the OutputClass constructor that takes a string type as an argument.  The initializer helps you to ensure your class fields are initialized when a class is instantiated.
The example above illustrates how a class can have multiple constructors.  The specific constructor called depends on the number of parameters and the type of each parameter.
In C#, there are two types of class members, instance and static.  Instance class members belong to a specific occurrence of a class.  Every time you declare an object of a certain class, you create a new instance of that class.  The ExampleClass Main() method creates an instance of the OutputClass named outCl.  You can create multiple instances of OutputClass with different names.  Each of these instances are separate and stand alone.  For example, if you create two OutputClass instances as follows:
    OutputClass oc1 = new OutputClass("OutputClass1");
    OutputClass oc2 = new OutputClass("OutputClass2");

You create two separate instances of OutputClass with separate myString fields and separate printString() methods.  On the other hand, if a class member is static, you can access it simply by using the syntax ..  The instance names are oc1 and oc2.  
Suppose OutputClass had the following static method:
    public static void staticPrinter()
    {
        Console.WriteLine("There is only one of me.");
    }

Then you could call that function from Main() like this:
    OutputClass.staticPrinter();
You must call static class members through their class name and not their instance name.  This means that you don't need to instantiate a class to use its static members.  There is only ever one copy of a static class member.   A good use of static members is when there is a function to be performed and no intermediate state is required, such as math calculations.  Matter of fact, the .NET Frameworks Base Class Library includes a Math class that makes extensive use of static members.
Another type of constructor is the static constructor.  Use static constructor to initialize static fields in a class .  You declare a static constructor by using the keyword static just in front of the constructor name.  A static constructor is called before an instance of a class is created, before a static member is called, and before the static constructor of a derived class (covered in a later chapter).  They are called only once.
OutputClass also has a destructor.  Destructors look just like constructors, except they have a tilde, "~", in front of them.  They don't take any parameters and do not return a value.  Destructors are places where you could put code to release any resources your class was holding during its lifetime.  They are normally called when the C# garbage collector decides to clean your object from memory.
So far, the only class members you've seen are Fields, Methods, Constructors, and Destructors.  Here is a complete list of the types of members you can have in your classes:
  • Constructors
  • Destructors
  • Fields
  • Methods
  • Properties
  • Indexers
  • Delegates
  • Events
  • Nested Classes
Those items not covered in this lesson will be covered in later lessons.
In summary, you can declare instance and static constructors.  You know how to initialize class fields.  When there is no need to instantiate an object, you can create static class members.  You can also declare destructors for cleaning up resources.

Lesson 8: Class Inheritance

This lesson teaches about C# Inheritance.  Our objectives are as follows:
  • Implement Base Classes.
  • Implement Derived Classes.
  • Initialize Base Classes from Derived Classes.
  • Learn How to Call Base Class Members.
  • Learn How to Hide Base Class Members.
Inheritance is one of the primary concepts of object-oriented programming.  It allows you to reuse existing code.  Through effective employment of reuse, you can save time in your programming.
Listing 8-1.  Inheritance:  BaseClass.cs
using System;

public class ParentClass
{
    public ParentClass()
    {
        Console.WriteLine("Parent Constructor.");
    }

    public
void print()
    {
        Console.WriteLine("I'm a Parent Class.");
    }
}

public
class ChildClass : ParentClass
{
    public ChildClass()
    {
        Console.WriteLine("Child Constructor.");
    }

    public
static void Main()
    {
        ChildClass child = new ChildClass();

        child.print();
    }
}

Output:
Parent Constructor.
 
Child Constructor.
 
I'm a Parent Class.
Listing 8-1 shows two classes.  The top class is named ParentClass and the main class is called ChildClass.  What we want to do is create a child class, using existing code from ParentClass.
First we must declare our intention to use ParentClass as the base class of ChildClass.  This is accomplished through the ChildClass declaration public class ChildClass : ParentClass.  The base class is specified by adding a colon, ":", after the derived class identifier and then specifying the base class name.
C# supports single class inheritance only.  Therefore, you can specify only one base class to inherit from.  However, it does allow multiple interface inheritance, a subject covered in a later lesson.
ChildClass has exactly the same capabilities as ParentClass.  Because of this, you can also say ChildClass "is" a ParentClass.  This is shown in the Main() method of ChildClass when the print() method is called.  ChildClass does not have its own print() method, so it uses the ParentClass print() method.  You can see the results in the 3rd line of output.
Base classes are automatically instantiated before derived classes.  Notice the output from Listing 8-1.  The ParentClass constructor executed before the ChildClass constructor.
Listing 8-2.  Derived Class Communicating with Base Class:  BaseTalk.cs
using System;

public class Parent
{
    string parentString;
    public Parent()
    {
        Console.WriteLine("Parent Constructor.");
    }
    public Parent(string myString)
    {
        parentString = myString;
        Console.WriteLine(parentString);
    }
    public void print()
    {
        Console.WriteLine("I'm a Parent Class.");
    }
}

public class Child : Parent
{
    public Child() : base("From Derived")
    {
        Console.WriteLine("Child Constructor.");
    }
    public new void print()
    {
        base.print();
        Console.WriteLine("I'm a Child Class.");
    }
    public static void Main()
    {
        Child child = new Child();
        child.print();
        ((Parent)child).print();
    }
}

Output:
From Derived
Child Constructor.
I'm a Parent Class.
I'm a Child Class.
I'm a Parent Class.
Derived classes can communicate with base classes during instantiation.  Listing 8-2 shows how this is done at the child constructor declaration.  The colon, ":", and keyword base call the base class constructor with the matching parameter list.  The first line of output shows the base class constructor being called with the string "From Derived".
Sometimes you may want to create your own implementation of a method that exists in a base class.  The Child class does this by declaring its own print() method.  The Child print() method hides the Parent print() method.  The effect is the Parent print() method will not be called, unless we do something special to make sure it is called.
Inside the Child print() method, we explicitly call the Parent print() method.  This is done by prefixing the method name with "base.".  Using the base keyword, you can access any of a base class public or protected class members.  The output from the Child print() method is on output lines 3 and 4.
Another way to access base class members is through an explicit cast.  This is done in the last statement of the Child class Main() method.  Remember that a derived class is a specialization of its base class.  This fact allows us to perform a cast on the derived class, making it an instance of its base class.  The last line of output from Listing 8-2 shows the Parent print() method was indeed executed.
Notice the new modifier on the Child class print() method.  This enables this method to hide the Parent class print() method, thus explicitly preventing polymorphism.  Without the new modifier, the compiler will produce a warning to draw your attention to this.  See the next lesson for a detailed discussion of polymorphism.
In summary, you know how to create a derived/base class relationship.  You can control instantiation of your base class and call its methods either implicitly or explicitly.  You also understand that a derived class is a specialization of its base class.

Lesson 9: Polymorphism

This lesson teaches about Polymorphism in C#. Our objectives are as follows:
  • Learn What Polymorphism Is.
  • Implement a Virtual Method.
  • Override a Virtual Method.
  • Use Polymorphism in a Program.
Another primary concept of object-oriented programming is Polymorphism. It allows you to implement derived class methods through a base class pointer during run-time. This is handy when you need to assign a group of objects to an array and then invoke each of their methods. They won't necessarily have to be the same object type. However, if they're related by inheritance, you can add them to the array as the inherited type. Then if they all share the same method name, that method of each object can be invoked. This lesson will show you how to accomplish this.
Listing 9-1. A Base Class With a Virtual Method: DrawingObject.cs
using System;

public class DrawingObject
{
    public virtual void Draw()
    {
        Console.WriteLine("I'm just a generic drawing object.");
    }
}

Listing 9-1 shows the DrawingObject class. This will be the base class for other objects to inherit from. It has a single method named Draw(). The Draw() method has a virtual modifier. The virtual modifier indicates to derived classes that they can override this method. The Draw() method of the DrawingObject class performs a single action of printing the statement, "I'm just a generic drawing object.", to the console.
Listing 9-2. Derived Classes With Override Methods: Line.cs, Circle.cs, and Square.cs
using System;

public class Line : DrawingObject
{
    public override void Draw()
    {
        Console.WriteLine("I'm a Line.");
    }
}

public
class Circle : DrawingObject
{
    public override void Draw()
    {
        Console.WriteLine("I'm a Circle.");
    }
}

public
class Square : DrawingObject
{
    public override void Draw()
    {
        Console.WriteLine("I'm a Square.");
    }
}

Listing 9-2 shows three classes. These classes inherit the DrawingObject class. Each class has a Draw() method and each Draw() method has an override modifier. The override modifier allows a method to override the virtual method of its base class at run-time. The override will happen only if the class is referenced through a base class reference. Overriding methods must have the same signature, name and parameters, as the virtual base class method it is overriding.
Listing 9-3. Program Implementing Polymorphism: DrawDemo.cs
using System;

public class DrawDemo
{
    public static int Main( )
    {
        DrawingObject[] dObj = new DrawingObject[4];

        dObj[0] = new Line();
        dObj[1] = new Circle();
        dObj[2] = new Square();
        dObj[3] = new DrawingObject();

        foreach
(DrawingObject drawObj in dObj)
        {
            drawObj.Draw();
        }

        return 0;
    }
}


Listing 9-3 shows a program that uses the classes defined in Listing 9-1 and Listing 9-2. This program implements polymorphism. In the Main() method of the DrawDemo class, there is an array being created. The type of object in this array is the DrawingObject class. The array is named dObj and is being initialized to hold four objects of type DrawingObject.
Next the dObj array is initialized. Because of their inheritance relationship with the DrawingObject class, the Line, Circle, and Square classes can be assigned to the dObj array. Without this capability, you would have to create an array for each type. Inheritance allows derived objects to act like their base class, which saves work.
After the array is initialized, there is a foreach loop that looks at each element of the array. Within the foreach loop the Draw() method is invoked on each element of the dObj array. Because of polymorphism, the run-time type of each object is invoked. The type of the reference object from the dObj array is a DrawingObject. However, that doesn't matter because the derived classes override the virtual Draw() method of the DrawingObject class. This makes the overriden Draw() methods of the derived classes execute when the Draw() method is called using the DrawingObject base class reference from the dObj array. Here's what the output looks like:
Output:
I'm a Line.
 
I'm a Circle.
 
I'm a Square.
 
I'm just a generic drawing object.
The override Draw() method of each derived class executes as shown in the DrawDemo program. The last line is from the virtual Draw() method of the DrawingObject class. This is because the actual run-time type of the fourth array element was a DrawingObject object.
The code in this lesson can be compiled with the following command line:
    csc DrawDemo.cs DrawingObject.cs Circle.cs Line.cs Square.cs
It will create the file DrawDemo.exe, which defaulted to the name of the first file on the command line.
In summary, you should now have a basic understanding of polymorphism.  You know how to define a virtual method. You can implement a derived class method that overrides a virtual method. This relationship between virtual methods and the derived class methods that override them enables polymorphism. This lesson showed how to use this relationship between classes to implement polymorphism in a program.

Lesson 10: Properties

This lesson teaches C# Properties. Our objectives are as follows:
  • Understand What Properties Are For.
  • Implement a Property.
  • Create a Read-Only Property.
  • Create a Write-Only Property.
Properties provide the opportunity to protect a field in a class by reading and writing to it through the property.  In other languages, this is often accomplished by programs implementing specialized getter and setter methods.  C# properties enable this type of protection while also letting you access the property just like it was a field.  To get an appreciation for what properties accomplish, let's take a look at how to provide field encapsulation by traditional methods.
Listing 10-1.  An Example of Traditional Class Field Access:  Accessors.cs
using System;

public
class PropertyHolder
{
    private int someProperty = 0;

    public int getSomeProperty()
    {
        return someProperty;
    }

    public
void setSomeProperty(int propValue)
    {
        someProperty = propValue;
    }

}

public
class PropertyTester
{
    public static int Main(string[] args)
    {
        PropertyHolder propHold = new PropertyHolder();

        propHold.setSomeProperty(5);

        Console.WriteLine("Property Value: {0}", propHold.getSomeProperty());

        return 0;
    }
}

Listing 10-1 shows the traditional method of accessing class fields.  The PropertyHolder class has the field we're interested in accessing.  It has two methods, getSomeProperty() and setSomeProperty().  The getSomeProperty() method returns the value of the someProperty field.  The setSomeProperty() method sets the value of the someProperty field.
The PropertyTester class uses the methods of the PropertyHolder class to get the value of the someProperty field in the PropertyHolder class.  The Main() method instantiates a new PropertyHolder object, propHold.  Next it sets the someMethod of propHold to the value 5 by using the setSomeProperty method.  Then the program prints out the property value with a Console.WriteLine() method call.  The argument used to obtain the value of the property is a call to the getSomeProperty() method of the propHold object.  It prints out "Property Value: 5" to the console.
This method of accessing information in a field has been good because it supports the object-oriented concept of encapsulation.  If the implementation of someProperty changed from an int type to a byte type, this would still work.  Now the same thing can be accomplished much smoother with properties.
Listing 10-2.  Accessing Class Fields With Properties:  Properties.cs
using System;

public class PropertyHolder
{
    private int someProperty = 0;

    public int SomeProperty
    {
        get
       {
            return someProperty;
        }
        set
       {
            someProperty = value;
        }
    }
}

public
class PropertyTester
{
    public static int Main(string[] args)
    {
        PropertyHolder propHold = new PropertyHolder();

        propHold.SomeProperty = 5;

        Console.WriteLine("Property Value: {0}", propHold.SomeProperty);

        return 0;
    }
}

Listing 10-2 shows how to create and use a property.  The PropertyHolder class has the SomeProperty property implementation.  Notice that the first letter of the first word is capitalized.  That's the only difference between the names of the property SomeProperty and the field someProperty.  The property has two accessors, get and set.  The get accessor returns the value of the someProperty field.  The set accessor sets the value of the someProperty field with the contents of value.  The value shown in the set accessor is a C# reserved word. 
The PropertyTester class uses the SomeProperty property in the PropertyHolder class.  The first line of the Main() method creates a PropertyHolder object named propHold.  Next the value of the someProperty field of the propHold object is set to 5 by using the SomeProperty property.  It is that simple -- just assign the value to the property as if it were a field.
After that, the Console.WriteLine() method prints the value of the someProperty field of the propHold object.  It does this by using the SomeProperty property of the propHold object.  Again, it is that simple -- just use the property as if it were a field itself.
Properties can be made read-only.  This is accomplished by having only a get accessor in the property implementation.
Listing 10-3.  Read-Only Property:  ReadOnlyProperty.cs
using System;

public class PropertyHolder
{
    private int someProperty = 0;

    public PropertyHolder(int propVal)
    {
        someProperty = propVal;
    }

    public
int SomeProperty
    {
        get
       {
            return someProperty;
        }
    }
}

public class PropertyTester
{
    public static int Main(string[] args)
    {
        PropertyHolder propHold = new PropertyHolder(5);

        Console.WriteLine("Property Value: {0}", propHold.SomeProperty);

        return 0;
    }
}

Listing 10-3 shows how to implement a read-only property.  The PropertyHolder class has a SomeProperty property that only implements a get accessor.  It leaves out the set accessor.  This particular PropertyHolder class has a constructor which accepts an int parameter.
The Main() method of the PropertyTester class creates a new PropertyHolder object named propHold.  The instantiation of the propHold object uses the constructor of the PropertyHolder that takes an int parameter.  In this case, it is set to 5.  This initializes the someProperty field of the propHold object to 5.
Since the SomeProperty property of the PropertyHolder class is read-only, there is no other way to set the value of the someProperty field.  If you inserted propHold.SomeProperty = 7 into the listing, the program would not compile, because SomeProperty is read-only.  When the SomeProperty property is used in the Console.WriteLine() method, it works fine.  This is because it is a read operation which only invokes the get accessor of the SomeProperty property.
Listing 10-4.  Write-Only Property:  WriteOnlyProperty.cs
using System;

public class PropertyHolder
{
    private int someProperty = 0;

    public int SomeProperty
    {
        set
       {
            someProperty = value;

            Console.WriteLine("someProperty is equal to {0}", someProperty);
        }
    }
}

public class PropertyTester
{
    public static int Main(string[] args)
    {
        PropertyHolder propHold = new PropertyHolder();

        propHold.SomeProperty = 5;

        return 0;
    }
}

Listing 10-4 shows how to create and use a write-only property.  This time the get accessor is removed from the SomeProperty property of the PropertyHolder class.  The set accessor has been added, with a bit more logic.  It prints out the value of the someProperty field after it has been modified.
The Main() method of the PropertyTester class instantiates the PropertyTester class with a default constructor.  Then it uses the SomeProperty property of the propHold object to set the someProperty field of the propHold object to 5.  This invokes the set accessor of the propHold object, which sets the value of its someProperty field to 5 and then prints "someProperty is equal to 5" to the console.
In summary, you now know what properties are for and how they're used.  Traditional methods of encapsulation have relied on separate methods.  Properties allow you to access objects state as if it was a field.  Properties can be made read-only or write-only and you know how to implement each type.

Lesson 11: Indexers

This lesson teaches C# Indexers. Our objectives are as follows:
  • Understand What Indexers Are For.
  • Implement an Indexer.
  • Overload Indexers.
  • Understand How to Implement Multi-Parameter Indexers.
Indexers are real easy.  They allow your class to be used just like an array.  On the inside of a class, you manage a collection of values any way you want.  These objects could be a finite set of class members, another array, or some complex data structure.  Regardless of the internal implementation of the class, its data can be obtained consistently through the use of indexers.  Here's an example.
Listing 11-1.  An Example of An Indexer:  IntIndexer.cs
using System;

class IntIndexer
{
    private string[] myData;

    public IntIndexer(int size)
    {
        myData = new string[size];

        for (int i=0; i < size; i++)
        {
            myData[i] = "empty";
        }
    }

    public
string this[int pos]
    {
        get
       {
            return myData[pos];
        }
        set
       {
            myData[pos] = value;
        }
    }

    static
void Main(string[] args)
    {
        int size = 10;

        IntIndexer myInd = new IntIndexer(size);

        myInd[9] = "Some Value";
        myInd[3] = "Another Value";
        myInd[5] = "Any Value";

        Console.WriteLine("\nIndexer Output\n");

        for
(int i=0; i < size; i++)
        {
            Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
        }
    }
}

Listing 11-1 shows how to implement an Indexer.  The IntIndexer class has a string array named myData.  This is a private array that external users can't see.  this array is initialized in the constructor, which accepts an int size parameter, instantiates the myData array, and then fills each element with the word "empty".
The next class member is the Indexer, which is identified by the this keyword and square brackets, this[int pos].  It accepts a single position parameter, pos.  As you may have already guessed, the implementation of an Indexer is the same as a Property.  It has get and set accessors that are used exactly like those in a Property.  This indexer returns a string, as indicated by the string return value in the Indexer declaration.
The Main() method simply instantiates a new IntIndexer object, adds some values, and prints the results.  Here's the output:
Indexer Output
 
myInd[0]: empty
myInd[1]: empty
myInd[2]: empty
myInd[3]: Another Value
myInd[4]: empty
myInd[5]: Any Value
myInd[6]: empty
myInd[7]: empty
myInd[8]: empty
myInd[9]: Some Value
Using an integer is a common means of accessing arrays in many languages, but the C# Indexer goes beyond this.  Indexers can be declared with multiple parameters and each parameter may be a different type.  Additional parameters are separated by commas, the same as a method parameter list.  Valid parameter types for Indexers include integers, enums, and strings.  Additionally, Indexers can be overloaded.  In listing 11-2, we modify the previous program to accept overloaded Indexers that accept different types.
Listing 11-2.  Overloaded Indexers:  OvrIndexer.cs
using System;

class OvrIndexer
{
    private string[] myData;
    private int         arrSize;

    public OvrIndexer(int size)
    {
        arrSize = size;
        myData = new string[size];

        for (int i=0; i < size; i++)
        {
            myData[i] = "empty";
        }
    }

    public
string this[int pos]
    {
        get
       {
            return myData[pos];
        }
        set
       {
            myData[pos] = value;
        }
    }

    public
string this[string data]
    {
        get
       {
            int count = 0;

            for
(int i=0; i < arrSize; i++)
            {
                if (myData[i] == data)
                {
                    count++;
                }
            }
            return count.ToString();
        }
        set
       {
            for (int i=0; i < arrSize; i++)
            {
                if (myData[i] == data)
                {
                    myData[i] = value;
                }
            }
        }
    }

    static
void Main(string[] args)
    {
        int size = 10;
        OvrIndexer myInd = new OvrIndexer(size);

        myInd[9] = "Some Value";
        myInd[3] = "Another Value";
        myInd[5] = "Any Value";

        myInd["empty"] = "no value";

        Console.WriteLine("\nIndexer Output\n");

        for
(int i=0; i < size; i++)
        {
            Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
        }

        Console.WriteLine("\nNumber of \"no value\" entries: {0}", myInd["no value"]);
    }
}

Listing 11-2 shows how to overload Indexers.  The first Indexer, with the int parameter, pos, is the same as in Listing 11-1, but there is a new Indexer that takes a string parameter.  The get accessor of the new indexer returns a string representation of the number of items that match the parameter value, data.  The set accessor changes each entry in the array that matches the data parameter to the value that is assigned to the Indexer.
The behavior of the overloaded Indexer that takes a string parameter is demonstrated in the Main() method of Listing 11-2.  It invokes the set accessor, which assigns the value of "no value" to every member of the myInd class that has the value of "empty".  It uses the following command:  myInd["empty"] = "no value";.  After each entry of the myInd class is printed, a final entry is printed to the console, indicating the number of entries with the "no value" string.  This happens by invoking the get accessor with the following code:  myInd["no value"}.  Here's the output:
Indexer Output
 
myInd[0]: no value
myInd[1]: no value
myInd[2]: no value
myInd[3]: Another Value
myInd[4]: no value
myInd[5]: Any Value
myInd[6]: no value
myInd[7]: no value
myInd[8]: no value
myInd[9]: Some Value
 
Number of "no value" entries: 7
The reason both Indexers in Listing 11-2 can coexist in the same class is because they have different signatures.  An Indexer signature is specified by the number and type of parameters in an Indexers parameter list.  The class will be smart enough to figure out which Indexer to invoke, based on the number and type of arguments in the Indexer call.  An indexer with multiple parameters would be implemented something like this:
    public object this[int param1, ..., int paramN]
    {
        get
       {
            // process and return some class data
        }
        set
       {
            // process and assign some class data
        }
    }

In summary, you now know what Indexers are for and how they're used.  You can create an Indexer to access class members similar to arrays.  Overloaded and multi-parameter Indexers were also covered.

Lesson 12: Structs

This lesson teaches C# Structs. Our objectives are as follows:
  • Understand Types in C#
  • Understand Boxing and Unboxing
  • Understand the Purpose of structs.
  • Implement a struct.
  • Use a struct.
Types:
C# supports two kinds of types: value types and reference types. Value types include simple types (e.g., char, int, and float), enum types, and struct types. Reference types include class types, interface types, delegate types, and array types.

Value types differ from reference types in that variables of the value types directly contain their data, whereas variables of the reference types store references to objects. With reference types, it is possible for two variables to reference the same object, and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other.
The example
using System;
class Class1
{
   public int Value = 0;
}
class Test
{
   static void Main() {
      int val1 = 0;
      int val2 = val1;
      val2 = 123;
      Class1 ref1 = new Class1();
      Class1 ref2 = ref1;
      ref2.Value = 123;
      Console.WriteLine("Values: {0}, {1}", val1, val2);
      Console.WriteLine("Refs: {0}, {1}", ref1.Value, ref2.Value);
   }
}
shows this difference. The output produced is
Values: 0, 123
Refs: 123, 123
The assignment to the local variable val1 does not impact the local variable val2 because both local variables are of a value type (the type int) and each local variable of a value type has its own storage. In contrast, the assignment ref2.Value = 123; affects the object that both ref1 and ref2 reference.
Boxing and unboxing:
The concept of boxing and unboxing is central to C#'s type system. It provides a bridge between value-types and reference-types by permitting any value of a value-type to be converted to and from type object. Boxing and unboxing enables a unified view of the type system wherein a value of any type can ultimately be treated as an object.
A boxing conversion permits a value-type to be implicitly converted to a reference-type.
using System;
class MethodParams
{
    public static void Main()
    {
            int i=1001;                                 //Boxing
            object obj = (object)  i;
            Console.WriteLine(obj.ToString());
     }
}
An unboxing conversion permits a reference-type to be explicitly converted to a value-type
using System;
class MethodParams
{
    public static void Main()
    {
            object box = 123;                                   //UnBoxing
            int i = (int)box;
            Console.WriteLine(i.ToString());
     }
}
Structs:
A struct allows you to create new value-type objects that are similar to the built-in types (int, float, bool, etc.).  When would you use a struct instead of a class?  Think about how the built-in types are used.  They have values and distinct operations to manipulate those values.  If you have a need to create an object that behaves in this manner, consider implementing it as a struct.  Later in this article, I'll explain a couple rules for using structs, which will give you a better idea of when to use them.  In the meantime, here's an example.
Listing 12-1.  Example of a struct:  StructExample.cs
using System;

struct Point
{
    public int x;
    public int y;

    public
Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public
Point Add(Point pt)
    {
        Point newPt;

        newPt.x = x + pt.x;
        newPt.y = y + pt.y;

        return
newPt;
    }
}

///
///
Example of declaring and using a struct
///
class StructExample
{
    static void Main(string[] args)
    {
        Point pt1 = new Point(1, 1);
        Point pt2 = new Point(2, 2);
        Point pt3;

        pt3 = pt1.Add(pt2);

        Console.WriteLine("pt3: {0}:{1}", pt3.x, pt3.y);
    }
}

Listing 12-1 shows how to declare and use a struct.  It is easy to tell that a type is a struct because of the keyword struct used in its definition.  The basic layout of a struct is much like a class, but with differences, which will be explained in following paragraphs.  The Point struct has a constructor which initializes its fields to the x and y values passed in.  It also has a method named Add(), which will accept another Point struct, add it to this struct, and return a new struct.
Notice that there is a Point struct declared in the Add() method.  It does not need to be instantiated with a new operator, like a class.  When this occurs, the struct is implicitly instantiated with its default (or parameterless) constructor.  The parameterless constructor initializes all struct fields to default values.  i.e. integrals are 0, floating points are 0.0, and booleans are false.  It's illegal to define a parameterless constructor for a struct.
Although not required, a struct may be instantiated with a new operator.  In Listing 12-1 the pt1 and pt2 Point structs are initialized with values by using the constructor defined in the Point struct.  A third Point struct, pt3 is declared and defaults to using the parameterless (default) constructor, because it doesn't matter what it's value is at this point.  The Add() method of the pt1 struct is then invoked, passing the pt2 struct as a parameter.  The result is assigned to pt3, showing that a struct may be used just like any other value type.  Here's the output from Listing 12-1:
        pt3: 3:3
Another difference between structs and classes is that structs can not have destructors.  Also, structs cannot inherit another class or struct or be inherited from.  However, a struct may inherit multiple interfaces.  An interface is a C# reference type with members that do not have implementations.  Any class or struct inheriting an interface must implement every one of that interface's methods.  Interfaces are a subject for a later lesson.
In summary, you now know how to create a struct.  You can also instantiate and use structs.  When deciding whether to implement a type as a struct or class, you should consider how the type will be used.  If you need to define a parameterless constructor, then a class is your only choice.  Also, consider that a struct incurs less overhead than a class because, being a value type, it is stored on the stack rather than how a class is stored, on the heap.

Lesson 13: Interfaces

This lesson teaches C# Interfaces.  Our objectives are as follows:
  • Understand Abstract Classes
  • Understand the Purpose of Interfaces.
  • Define an Interface.
  • Use an Interface.
  • Implement Interface Inheritance.
  • Understand difference between Interface and Abstract classes.
Abstract Classes:
The abstract modifier is used to indicate that a class is incomplete and that it is intended to be used only as a base class. An abstract class differs from a non-abstract class in the following ways:
An abstract class cannot be instantiated directly, and it is a compile-time error to use the new operator on an abstract class. While it is possible to have variables and values whose compile-time types are abstract, such variables and values will necessarily either be null or contain references to instances of non-abstract classes derived from the abstract types.
An abstract class is permitted (but not required) to contain abstract members.
An abstract class cannot be sealed.
When a non-abstract class is derived from an abstract class, the non-abstract class must include actual implementations of all inherited abstract members, thereby overriding those abstract members. In the example
abstract class A
{
   public abstract void F();
}
abstract class B: A
{
   public void G() {}
}
class C: B
{
   public override void F() {
      // actual implementation of F
   }
}
the abstract class A introduces an abstract method F. Class B introduces an additional method G, but since it doesn't provide an implementation of F, B must also be declared abstract. Class C overrides F and provides an actual implementation. Since there are no abstract members in C, C is permitted (but not required) to be non-abstract.
Interfaces:
An interface looks like a class, but has no implementation.  The only thing it contains are definitions of events, indexers, methods and/or properties.  The reason interfaces only provide definitions is because they are inherited by classes and structs, which must provide an implementation for each interface member defined.
So, what are interfaces good for if they don't implement functionality?  They're great for putting together plug-n-play like architectures where components can be interchanged at will.  Since all interchangeable components implement the same interface, they can be used without any extra programming.  The interface forces each component to expose specific public members that will be used in a certain way.
Because interfaces must be defined by inheriting classes and structs, they define a contract.  For instance, if class foo inherits from the IDisposable interface, it is making a statement that it guarantees it has the Dispose() method, which is the only member of the IDisposable interface.  Any code that wishes to use class foo may check to see if class foo inherits IDisposable.  When the answer is true, then the code knows that it can call foo.Dispose().  Listing 13-1 shows how to define an interface:
Listing 13-1.  Defining an Interface:  MyInterface.cs
interface IMyInterface
{
    void MethodToImplement();
}

Listing 13-1 shows defines an interface named IMyInterface.  A common naming convention is to prefix all interface names with a capital "I".  This interface has a single method named MethodToImplement().  This could have been any type of method declaration with different parameters and return types.  I just chose to declare this method with no parameters and a void return type to make the example easy.  Notice that this method does not have an implementation (instructions between curly braces - {}), but instead ends with a semi-colon, ";".  This is because the interface only specifies the signature of methods that an inheriting class or struct must implement.  Listing 13-2 shows how this interface could be used.
Listing 13-2.  Using an Interface:  InterfaceImplementer.cs
class InterfaceImplementer : IMyInterface
{
    static void Main()
    {
        InterfaceImplementer iImp = new InterfaceImplementer();
        iImp.MethodToImplement();
    }

    public
void MethodToImplement()
    {
        Console.WriteLine("MethodToImplement() called.");
    }
}

The InterfaceImplementer class in Listing 13.2 implements the IMyInterface interface.  Indicating that a class inherits an interface is the same as inheriting a class.  In this case, the following syntax is used:
class InterfaceImplementer : IMyInterface
Now that this class inherits the IMyInterface interface, it must implement its members.  It does this by implementing the MethodToImplement() method.  Notice that this method implementation has the exact same signature, parameters and method name, as defined in the IMyInterface interface.  Any difference will cause a compiler error.  Interfaces may also inherit other interfaces.  Listing 13-3 shows how inherited interfaces are implemented.
Listing 13-3.  Interface Inheritance:  InterfaceInheritance.cs
using System;

interface IParentInterface
{
    void ParentInterfaceMethod();
}

interface
IMyInterface : IParentInterface
{
    void MethodToImplement();
}

class
InterfaceImplementer : IMyInterface
{
    static void Main()
    {
        InterfaceImplementer iImp = new InterfaceImplementer();
        iImp.MethodToImplement();
        iImp.ParentInterfaceMethod();
    }

    public
void MethodToImplement()
    {
        Console.WriteLine("MethodToImplement() called.");
    }

    public void ParentInterfaceMethod()
    {
        Console.WriteLine("ParentInterfaceMethod() called.");
    }
}

The code in listing 13.3 contains two interfacesIMyInterface and the interface it inherits, IParentInterface.  When one interface inherits another, any implementing class or struct must implement every interface member in the entire inheritance chain.  Since the InterfaceImplementer class in Listing 13-3 inherits from IMyInterface, it also inherits IParentInterface.  Therefore, the InterfaceImplementer class must implement the MethodToImplement() method specified in the IMyInterface interface and the ParentInterfaceMethod() method specified in the IParentInterface interface.
Difference between abstract classes and Intrfaces:
1.an abstract class can have implementation and an interface cannot,
2.an abstract class can declare methods as virtual which removes the requirement for a derrived class to implement those specific methods,
3.an abstract class defines modifiers (public/protected/etc) for members which an interface does not.
In summary, you now understand what interfaces are.  You can implement an interface and use it in a class.  Interfaces may also be inherited by other interface.  Any class or struct that inherits an interface must also implement all members in the entire interface inheritance chain.

Lesson 14: Introduction to Delegates and Events

This lesson introduces delegates and events. Our objectives are as follows:
  • Understand What a Delegate Is
  • Understand What an Event Is
  • Implement Delegates
  • Fire Events

Delegates

During previous lessons, you learned how to implement reference types using language constructs such as classes and interfaces.  These reference types allowed you to create instances of objects and use them in special ways to accomplish your software development goals.  Classes allow you to create objects that contained members with attributes or behavior.  Interfaces allowed you to declare a set of attributes and behavior that all objects implementing them would publicly expose.  Today, I'm going to introduce a new reference type called a delegate.
A delegate is a C# language element that allows you to reference a method.  If you were a C or C++ programmer, this would sound familiar because a delegate is basically a function pointer and are type safe.  However, developers who have used other languages are probably wondering, "Why do I need a reference to a method?".  The answer boils down to giving you maximum flexibility to implement any functionality you want at runtime. 
Think about how you use methods right now.  You write an algorithm that does its thing by manipulating the values of variables and calling methods directly by name.  What if you wanted an algorithm that was very flexible, reusable, and allowed you to implement different functionality as the need arises?  Furthermore, let's say that this was an algorithm that supported some type of data structure that you wanted to have sorted, but you also want to enable this data structure to hold different types.  If you don't know what the types are, how could you decide an appropriate comparison routine?  Perhaps you could implement an if/then/else or switch statement to handle well-known types, but this would still be limiting and require overhead to determine the type.  Another alternative would be for all the types to implement an interface that declared a common method your algorithm would call, which is actually a nice solution.  However, since this lesson is about delegates, we'll apply a delegate solution, which is quite elegant.
You could solve this problem by passing a delegate to your algorithm and letting the contained method, which the delegate refers to, perform the comparison operation.  Such an operation is performed in Listing 14-1.
Listing 14-1.  Declaring and Implementing a Delegate:  SimpleDelegate.cs
using System;

// this is the delegate declaration
public delegate int Comparer(object obj1, object obj2);

public class Name
{
    public string FirstName = null;
    public string LastName = null;

    public
Name(string first, string last)
    {
        FirstName = first;
        LastName = last;
    }

    // this is the delegate method handler
    public
static int CompareFirstNames(object name1, object name2)
    {
        string n1 = ((Name)name1).FirstName;
        string n2 = ((Name)name2).FirstName;

        if
(String.Compare(n1, n2) > 0)
        {
            return 1;
        }
        else if (String.Compare(n1, n2) < 0)
        {
            return -1;
        }
        else
        {
            return 0;
        }
    }

    public
override string ToString()
    {
        return FirstName + " " + LastName;
    }
}

class
SimpleDelegate
{
    Name[] names = new Name[5];

    public
SimpleDelegate()
    {
        names[0] = new Name("Joe", "Mayo");
        names[1] = new Name("John", "Hancock");
        names[2] = new Name("Jane", "Doe");
        names[3] = new Name("John", "Doe");
        names[4] = new Name("Jack", "Smith");
    }

    static
void Main(string[] args)
    {
        SimpleDelegate sd = new SimpleDelegate();

        // this is the delegate instantiation
       
Comparer cmp = new Comparer(Name.CompareFirstNames);

        Console.WriteLine("\nBefore Sort: \n");

        sd.PrintNames();

        // observe the delegate argument
        sd.Sort(cmp);

        Console.WriteLine("\nAfter Sort: \n");

        sd.PrintNames();
    }

    // observe  the delegate parameter
    public void Sort(Comparer compare)
    {
        object temp;

        for
(int i=0; i < names.Length; i++)
        {
            for (int j=i; j < names.Length; j++)
            {
                // using delegate "compare" just like
                // a normal method
                if ( compare(names[i], names[j]) > 0 )
                {
                    temp = names[i];
                    names[i] = names[j];
                    names[j] = (Name)temp;
                }
            }
        }
    }

    public
void PrintNames()
    {
        Console.WriteLine("Names: \n");

        foreach
(Name name in names)
        {
            Console.WriteLine(name.ToString());
        }
    }
}

The first thing the program in Listing 14-1 does is declare a delegateDelegate declarations look somewhat like methods, except they have the delegate modifier, are terminated with a semi-colon (;), and have no implementation.  Below, is the delegate declaration from Listing 14-1.
public delegate int Comparer(object obj1, object obj2);
This delegate declaration defines the signature of a delegate handler method that this delegate can refer to.  The delegate handler method, for the Comparer delegate, can have any name, but must have a first parameter of type object, a second parameter of type object, and return an int type.  The following method from Listing 14-1 shows a delegate handler method that conforms to the signature of the Comparer delegate.
    public static int CompareFirstNames(object name1, object name2)
    {
        ...
    }

To use a delegate, you must create an instance of it.  The instance is created, similar to a class instance, with a single parameter identifying the appropriate delegate handler method, as shown below.
        Comparer cmp = new Comparer(Name.CompareFirstNames);
The delegate, cmp, is then used as a parameter to the Sort() method, which uses it just like a normal method.  Observe the way the delegate is passed to the Sort() method as a parameter in the code below. 
        sd.Sort(cmp);
Using this technique, any delegate handler method may be passed to the Sort() method at run-time.  i.e. You could define a method handler named CompareLastNames(), instantiate a new Comparer delegate instance with it, and pass the new delegate to the Sort() method.

Events

Traditional Console applications operate by waiting for a user to press a key or type a command and press the Enter key.  Then they perform some pre-defined operation and either quit or return to the original prompt that they started from.  This works, but is inflexible in that everything is hard-wired and follows a rigid path of execution.  In stark contrast, modern GUI programs operate on an event-based model.  That is, some event in the system occurs and interested modules are notified so they can react appropriately.  With Windows Forms, there is not a polling mechanism taking up resources and you don't have to code a loop that sits waiting for input  It is all built into the system with events.
A C# event is a class member that is activated whenever the event it was designed for occurs.  I like to use the term "fires" when the event is activated.  Anyone interested in the event can register and be notified as soon as the event fires.  At the time an event fires, registered methods will be invoked.
Events and delegates work hand-in-hand to provide a program's functionality.  It starts with a class that declares an event.  Any class, including the same class that the event is declared in, may register one of its methods for the event.  This occurs through a delegate, which specifies the signature of the method that is registered for the event.  The delegate may be one of the pre-defined .NET delegates or one you declare yourself.  Whichever is appropriate, you assign the delegate to the event, which effectively registers the method that will be called when the event fires.  Listing 14-2 shows a couple different ways to implement events.
Listing 14-2.  Declaring and Implementing Events:  EventDemo.cs
using System;
using System.Drawing;
using System.Windows.Forms;

// custom delegate
public delegate void StartDelegate();

class EventDemo : Form
{
    // custom event
    public event StartDelegate StartEvent;

    public EventDemo()
    {
        Button clickMe = new Button();

        clickMe.Parent = this;
        clickMe.Text = "Click Me";
        clickMe.Location = new Point(
            (ClientSize.Width - clickMe.Width) /2,
            (ClientSize.Height - clickMe.Height)/2);

        // an EventHandler delegate is assigned
        // to the button's Click event
        clickMe.Click += new EventHandler(OnClickMeClicked);

        // our custom "StartDelegate" delegate is assigned
        // to our custom "StartEvent" event.
        StartEvent += new StartDelegate(OnStartEvent);

        // fire our custom event
        StartEvent();
    }

    // this method is called when the "clickMe" button is pressed
    public void OnClickMeClicked(object sender, EventArgs ea)
    {
        MessageBox.Show("You Clicked My Button!");
    }

    // this method is called when the "StartEvent" Event is fired
    public void OnStartEvent()
    {
        MessageBox.Show("I Just Started!");
    }

    static
void Main(string[] args)
    {
        Application.Run(new EventDemo());
    }
}

You may have noticed that Listing 14-2 is a Windows Forms program.  Although I haven't covered Windows Forms in this tutorial, you should know enough about C# programming in general that you won't be lost. To help out, I'll give a brief explanation of some of the parts that you may not be familiar with.
The EventDemo class inherits Form, which essentially makes it a Windows Form.  This automatically gives you all the functionality of a Windows Form, including Title Bar, Minimize/Maximize/Close buttons, System Menu, and Borders.  A lot of power, that inheritance thing, eh?
The way a Windows Form's application is started is by calling the Run() method of the static Application object with a reference to the Form object as its parameter.  This starts up all the underlying Windows plumbing, displays the GUI, and ensures that events are fired as appropriate.
Let's look at the custom event first.  Below is the event declaration, which is a member of the EventDemo class.  It is declared with the event keyword, a delegate type, and an event name.
    public event StartDelegate StartEvent;
Anyone interested in an event can register by hooking up a delegate for that event.  On the next line, we have a delegate of type StartDelegate, which the event was declared to accept, hooked up to the StartEvent event.  The += syntax registers a delegate with an event.  To unregister with an event, use the -= with the same syntax.
        StartEvent += new StartDelegate(OnStartEvent);
Firing an event looks just like a method call, as shown below:
StartEvent();
This was how to implement events from scratch, declaring the event and delegate yourself.  However, much of the event programming you'll do will be with pre-defined events and delegates.  This leads us to the other event code you see in Listing 14-2, where we hook up an EventHandler delegate to a Button Click event.
        clickMe.Click += new EventHandler(OnClickMeClicked);
The Click event already belongs to the Button class and all we have to do is reference it when registering a delegate.  Similarly, the EventHandler delegate already exists in the System namespace of the .NET Frameworks Class Library.  All you really need to do is define your callback method (delegate handler method) that is invoked when someone presses the clickMe button.  The OnClickMeClicked() method, shown below, conforms to the signature of the EventHander delegate, which you can look up in the .NET Framework Class Library reference.
    public void OnClickMeClicked(object sender, EventArgs ea)
    {
        MessageBox.Show("You Clicked My Button!");
    }

Any time the clickMe button is pressed with a mouse, it will fire the Click event, which will invoke the OnClickMeClicked() method.  The Button class takes care of firing the Click event and there's nothing more you have to do.  Because it is so easy to use pre-defined events and delegates, it would be a good idea to check if some exist already that will do what you need, before creating your own.
This completes this lesson, which was an introduction to delegates and events.  You learned how to declare and implement delegates, which provide dynamic run-time method invocation services.  You also know how to declare events and use them in a couple different scenarios.  One way is to declare your own event, delegate, and callback method from scratch.  Another way is to use pre-existing events and delegates and only implement the callback method, which will save you time and make coding easier.

Lesson 15: Introduction to Exception Handling

This lesson teaches how to handle exceptions in you C# programs. Our objectives are as follows:
  • Learn what an exception is
  • Implement a routine with a try/catch block
  • Release resources in a finally block

Exceptions

Exceptions are unforeseen errors that happen in your programs.  Most of the time, you can, and should, detect and handle program errors in your code.  For example, validating user input, checking for null objects, and verifying the values returned from methods are what you expect, are all examples of good standard error handling that you should be doing all the time. 
However, there are times when you don't know if an error will occur.  For example, you can't predict when you'll receive a file I/O error, run out of system memory, or encounter a database error.  These things are generally unlikely, but they could still happen and you want to be able to deal with them when they do occur.  This is where exception handling comes in.
When exceptions occur, they are said to be "thrown".  What is actually thrown is an object that is derived from the System.Exception class.  In the next section, I'll be explaining how thrown exceptions are handled with try/catch blocks. 
The System.Exception class provides several methods and properties for obtaining information on what went wrong.  For example, the Message property provides summary information about what the error was, the StackTrace property provides information from the stack for where the problem occurred, and the ToString() method is overridden to reveal a verbose description of the entire exception.
Identifying the exceptions you'll need to handle depends on the routine you're writing.  For example, if the routine opened a file with the System.IO.File.OpenRead() method, it could throw any of the following exceptions:
  • SecurityException
  • ArgumentException
  • ArgumentNullException
  • PathTooLongException
  • DirectoryNotFoundException
  • UnauthorizedAccessException
  • FileNotFoundException
  • NotSupportedException
It's easy to find out what exceptions a method can raise by looking in the .NET Frameworks SDK Documentation.  Just go to the Reference/Class Library section and look in the Namespace/Class/Method documentation for the methods you use.  The exception in the list above were found by looking at the OpenRead() method definition of the File class in the System.IO namespace.  Each exception identified has a hyperlink to its class definition that you can use to find out what that exception is about.  Once you've figured out what exceptions can be generated in your code, you need to put the mechanisms in place to handle the exceptions, should they occur.

try/catch Blocks

When exceptions are thrown, you need to be able to handle them.  This is done by implementing a try/catch block.  Code that could throw an exception is put in the try block an exception handling code goes in the catch block.  Listing 15-1 shows how to implement a try/catch block.  Since an OpenRead() method could throw one of several exceptions, it is placed in the try block.  If an exception is thrown, it will be caught in the catch block.  The code in Listing 15-1 will print message and stack trace information out to the console if an exception is raised.
Note:  The programs in this lesson cause exceptions on purpose.  The exception that you see is generated intentionally to show you what the exception message looks like before you see it yourself in your own programs.
Listing 15-1.  Using try/catch Blocks:  TryCatchDemo.cs
using System;
using System.IO;

class TryCatchDemo
{
    static void Main(string[] args)
    {
        try
        {
            File.OpenRead("NonExistentFile");
        }
        catch(Exception ex)
        {
            Console.WriteLine("ex.ToString() = " + ex.ToString());
            Console.WriteLine("ex.Message = " + ex.Message);
            Console.WriteLine("ex.StackTrace = " + ex.StackTrace);
        }
    }
}

Although the code in Listing 15-1 only has a single catch block, all exceptions will be caught there because the type is of the base exception type "Exception".  In exception handling, more specific exceptions will be caught before their more general parent exceptions.  For example, the following snippet shows how to place multiple catch blocks:
        catch(FileNotFoundException fnfex)
        {
            Console.WriteLine(fnfex.ToString());
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

If the file doesn't exist, a FileNotFoundException exception will be thrown and caught by the first catch block.  However, if a PathTooLongException exception was raised, the second catch part would catch the exception.  This is because there isn't a catch block for the PathTooLongException exception and the generic Exception type catch block is the only option available to catch the exception.
Exceptions that are not handled will normally bubble up the stack until a calling routine in the call chain handles them.  If you forget to include try/catch blocks in a part of your code and there aren't any try/catch blocks earlier in the call chain, your program will abort with a message describing the exception.  To your users this would be very cryptic and uncomfortable.  It is good practice to provide exception handling in your programs.

Finally Blocks

An exception can leave your program in an inconsistent state by not releasing resources or doing some other type of cleanup.  A catch block is a good place to figure out what may have went wrong and try to recover, however it can't account for all scenarios.  Sometimes you need to perform clean up actions whether or not your program succeeds.  These situations are good candidates for using a finally block.
Listing 15-2 illustrates the usefulness of a finally block.  As you know, a file stream must be closed when your done with it.  In this case, the file stream is the resource that needs to be cleaned up.  In Listing 15-2, outStream is opened successfully, meaning the program now has a handle to an open file resource.  When trying to open the inStream, a FileNotFoundException exception is raised, causing control to go immediately to the catch block.
It's possible to close the outStream in the catch block, but what if the algorithm executed successfully without an exception?  On success, the file would never be closed.  Fortunately, we've included a finally block in Listing 15-2, which will always be executed.  That's right, regardless of whether the algorithm in the try block raises an exception or not, the code in the finally block will be executed before control leaves the method.
Listing 15-2.  Implementing a finally Block:  FinallyDemo.cs
using System;
using System.IO;

class FinallyDemo
{
    static void Main(string[] args)
    {
        FileStream outStream = null;
        FileStream inStream = null;

        try
        {
            outStream = File.OpenWrite("DestinationFile.txt");
            inStream = File.OpenRead("BogusInputFile.txt");
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        finally
        {
            if (outStream != null)
            {
                outStream.Close();
                Console.WriteLine("outStream closed.");
            }
            if (inStream != null)
            {
                inStream.Close();
                Console.WriteLine("inStream closed.");
            }
        }
    }
}

A finally block is not required and you may ask what happens if you just put code after the catch block.  True, under normal circumstances, if the exception is caught, all code following the catch will be executed.  However, try/catch/finally is for exceptional circumstances and it is better to plan for the worst to make your program more robust.  For example, if one of the catch handlers rethrew and exception or caused another exception, the code following the catch block (not in a finally block) would never be executed.  Also, if you don't catch the exception at all, program flow would immediately do a stack walk looking for an exception handler that fits and the code following the catch blocks would not be executed.  Since there is too much potential for code in an algorithm to not be executed, a finally block is your insurance for executing those critical actions you need.
This has been an introduction to handling exceptions.  By now, you should have a good understanding of what an exception is.  You can implement algorithms within try/catch blocks that handle exceptions.  Additionally, you know how to clean up resources by implementing a finally block whose code is always executed before leaving a method.

Lesson 16: Using Attributes

This lesson explains how to use C# attributes.  Our objectives are as follows:
  • Understand what attributes are and why they're used
  • Apply various attributes with multiple or no parameters
  • Use assembly, type member, and type level attributes

Why Attributes?

Attributes are elements that allow you to add declarative information to your programs.  This declarative information is used for various purposes during runtime and can be used at design time by application development tools.  For example, there are attributes such as DllImportAttribute that allow a program to communicate with the Win32 libraries.  Another attribute, ObsoleteAttribute, causes a compile-time warning to appear, letting the developer know that a method should no longer be used.  When building Windows Forms applications, there are several attributes that allow visual  components to be drag-n-dropped onto a visual form builder and have their information appear in the properties grid.  Attributes are also used extensively in securing .NET assemblies, forcing calling code to be evaluated against pre-defined security constraints.  These are just a few descriptions of how attributes are used in C# programs.
The reason attributes are necessary is because many of the services they provide would be very difficult to accomplish with normal code.  You see, attributes add what is called metadata to your programs.  When your C# program is compiled, it creates a file called an assembly, which is normally an executable or DLL library.  Assemblies are self-describing because they have metadata written to them when they are compiled.  Via a process known as reflection, a program's attributes can be retrieved from its assembly metadata.  Attributes are classes that can be written in C# and used to decorate your code with declarative information.  This is a very powerful concept because it means that your can extend your language by creating customized declarative syntax with attributes. 
This tutorial will show how to use pre-existing attributes in C# programs.  Understanding the concepts and how to use a few attributes, will help in finding the multitude of other pre-existing attributes in the .NET class libraries and use them also.

Attribute Basics

Attributes are generally applied physically in front of type and type member declarations.  They're declared with square brackets, "[" and "]", surrounding the attribute such as the following ObsoleteAttribute attribute:
[ObsoleteAttribute]
The "Attribute" part of the attribute name is optional.  So the following is equivalent to the attribute above:
[Obsolete]
You'll notice that the attribute is declared with only the name of the attribute, surrounded by square brackets.  Many attributes have parameter lists, that allow inclusion of additional information that customizes a program even further.  Listing 16.1 shows various ways of how to use the ObsoleteAttribute attribute.
Listing 16-1.  How to Use Attributes:  BasicAttributeDemo.cs
using System;

class BasicAttributeDemo
{
    [Obsolete]
    public void MyFirstDeprecatedMethod()
    {
        Console.WriteLine("Called MyFirstDeprecatedMethod().");
    }

    [ObsoleteAttribute]
    public void MySecondDeprecatedMethod()
    {
        Console.WriteLine("Called MySecondDeprecatedMethod().");
    }

    [Obsolete("You shouldn't use this method anymore.")]
    public void MyThirdDeprecatedMethod()
    {
        Console.WriteLine("Called MyThirdDeprecatedMethod().");
    }

    // make the program thread safe for COM
    [STAThread]
    static void Main(string[] args)
    {
        BasicAttributeDemo attrDemo = new BasicAttributeDemo();

        attrDemo.MyFirstDeprecatedMethod();
        attrDemo.MySecondDeprecatedMethod();
        attrDemo.MyThirdDeprecatedMethod();
    }
}

Examining the code in listing 16-1 reveals that the ObsoleteAttribute attribute was used a few different ways.  The first usage appeared on the MyFirstDeprecatedMethod() method and the second usage appeared in the MySecondDeprecatedMethod() method as follows:
    [Obsolete]
    public void MyFirstDeprecatedMethod()
    ...
    [ObsoleteAttribute]
    public void MySecondDeprecatedMethod()
    ...

The only difference between the two attributes is that MySecondDeprecatedMethod() method contains the "Attribute" in the attribute declaration.  The results of both attributes are exactly the same.  Attributes may also have parameters, as shown in the following declaration:
    [Obsolete("You shouldn't use this method anymore.")]
    public void MyThirdDeprecatedMethod()
    ...

This adds customized behavior to the ObsoleteAttribute attribute which produces different results from the other ObsoleteAttribute attribute declarations.  The results of all three ObsoleteAttribute attributes are shown below.  These are the warnings that are emitted by the C# compiler when the program is compiled:
>csc BasicAttributeDemo.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.2292.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
 
BasicAttributeDemo.cs(29,3): warning CS0612:
'BasicAttributeDemo.MyFirstDeprecatedMethod()' is obsolete
BasicAttributeDemo.cs(30,3): warning CS0612:
'BasicAttributeDemo.MySecondDeprecatedMethod()' is obsolete
BasicAttributeDemo.cs(31,3): warning CS0618:
'BasicAttributeDemo.MyThirdDeprecatedMethod()' is obsolete: 'You
shouldn't use this method anymore.' 
As you can see, the ObsoleteAttribute attribute caused the MyThirdDeprecatedMethod() method to emit the message that was a parameter to the ObsoleteAttribute attribute of that method in the code.  The other attributes simply emitted standard warnings.
Listing 16-1 also contains another attribute you're likely to see, the STAThreadAttribute attribute.  You'll often see this attribute applied to the Main() method, indicating that this C# program should communicate with unmanaged COM code using the Single Threading Apartment .  It is generally safe to use this attribute all the time because you never know when a 3rd party library you're using is going to be communicating with COM.  The following excerpt shows how to use the STAThreadAttribute attribute:
    [STAThread]
    static void Main(string[] args)
    ...

Attribute Parameters

Attributes often have parameters that enable customization.  There are two types of parameters that can be used on attributes, positional and named. Positional parameters are used when the attribute creator wishes the parameters to be required.  However, this is not a hard and fast rule because the ObsoleteAttribute attribute has a second positional parameter named error of type int that we can omit as demonstrated in Listing 16-1.  That attribute could have been written with the second positional parameter to force a compiler error instead of just a warning as follows:
    [Obsolete("You shouldn't use this method anymore.", true)]
    public void MyThirdDeprecatedMethod()
    ...

The difference between positional parameters and named parameters are that named parameters are specified with the name of the parameter and are always optional.  The DllImportAttribute attribute is one you are likely to see that has both positional and named attributes (Listing 16-2).
Listing 16-2.  Using Positional and Named Attribute Parameters:  AttributeParamsDemo.cs
using System;
using System.Runtime.InteropServices;

class AttributeParamsDemo
{
    [DllImport("User32.dll", EntryPoint="MessageBox")]
    static extern int MessageDialog(int hWnd, string msg, string caption, int msgType);

    [STAThread]
    static void Main(string[] args)
    {
        MessageDialog(0, "MessageDialog Called!", "DllImport Demo", 0);
    }
}

The DllImportAttribute attribute in Listing 16-2 has a one positional parameter, "User32.dll", and one named parameter, EntryPoint="MessageBox".  Positional parameters are always specified before any named parameters.  When there are named parameters, they may appear in any order.  This is because they are marked with the parameter name like in the DllImportAttribute attribute, EntryPoint="MessageBox".  Since the purpose of this lesson is to explain how to use attributes in general, I won't go into the details of the DllImportAttribute attribute, which has extra parameters that require knowledge of Win32 and other details that don't pertain to this lesson.  Many other attributes can be used with both positional and named parameters.

Attribute Targets

The attributes shown so far have been applied to methods, but there are many other C# language elements that you can use attributes with.  Table 16-1 outlines the C# language elements that attributes may be applied to.  They are formally called attribute "targets".
Attribute Target
Can be Applied To
all
everything
assembly
entire assembly
class
classes
constructor
constructors
delegate
delegates
enum
enumerations
event
events
field
fields
interface
interfaces
method
methods
module
modules (compiled code that can be part of an assembly)
parameter
parameters
property
properties
returnvalue
return values
struct
structures
Whenever there is ambiguity in how an attribute is applied, you can add a target specification to ensure the right language element is decorated properly.  An attribute that helps ensure assemblies adhere to the Common Language Specification (CLS) is the CLSCompliantAttribute attribute.  The CLS is the set of standards that enable different .NET languages to communicate.  Attribute targets are specified by prefixing the attribute name with the target and separating it with a colon (;).  Listing 16-3 shows how to use the CLSCompliantAttribute attribute and apply it to the entire assembly.
Listing 16-3.  Using Positional and Named Attribute Parameters:  AttributeTargetDemo.cs
using System;

[assembly:CLSCompliant(true)]

public
class AttributeTargetDemo
{
    public void NonClsCompliantMethod(uint nclsParam)
    {
        Console.WriteLine("Called NonClsCompliantMethod().");
    }

    [STAThread]
    static void Main(string[] args)
    {
        uint myUint = 0;

        AttributeTargetDemo tgtDemo = new AttributeTargetDemo();

        tgtDemo.NonClsCompliantMethod(myUint);
    }
}

The code in Listing 16-3 won't compile because the uint type parameter declared on the NonClsCompliantMethod() method.  If you change the CLSCompliantAttribute attribute to false or change the type of the NonClsCompliantMethod() method to a CLS compliant type, such as int, the program will compile. 
The point about Listing 16-3 is that the CLSCompliantAttribute attribute is decorated with an attribute target of "assembly".  This causes all members of this assembly to be evaluated according to the CLSCompliantAttribute attribute setting.  To limit the scope of the CLSCompliantAttribute, apply it to either the AttributeTargetDemo class or NonClsCompliantMethod() method directly.

Summary

Attributes are C# language elements that decorate program elements with additional metadata that describes the program.  This metadata is then evaluated at different places, such as runtime or design time for various purposes.  The examples in this lesson showed how the ObsoleteAttribute attribute could be used to generate compile time warnings for deprecated code.  Through applying the DllImportAttribute attribute, you could see how to apply both positional and named parameters to an attribute.  Attributes may also be used to decorate various different types of program elements with a target descriptor.  The example applied the CLSCompliantAttribute attribute to an entire assembly.  However, it could have also been applied to different program elements with applicable target descriptors to limit its scope. 

Lesson 17: Enums

This lesson explains how to use C# enums.  Our objectives are as follows:
  • Understand what an enum is
  • Be able to create new enum types
  • Learn how to use enums 
  • Gain familiarity with System.Enum type methods

Enums Defined

Enums are strongly typed constants.  They are essentially unique types that allow you to assign symbolic names to integral values. In the C# tradition, they are strongly typed, meaning that an enum of one type may not be implicitly assigned to an enum of another type even though the underlying value of their members are the same.  Along the same lines, integral types and enums are not implicitly interchangable. All assignments between different enum types and integral types require an explicit cast.
Enums lend themselves to more maintainable code because they are symbolic, allowing you to work with integral values, but using a meaningful name to do so. For example, what type of code would you rather work with - a set of values named North, South, East, and West or the set of integers 0, 1, 2, and 3 that mapped to the same values, respectively.  Enums make working with strongly typed constants via symbolic names easy.
Enums are value types, which means they contain their own value, can't inherit or be inherited from, and assignment copies the value of one enum to another.   You will see in this lesson and elsewhere that enums are used and referred to with both lower case, enum, and upper case, Enum.  Strangely enough, the relationship between the two is that the C# type, enum, inherits the Base Class Library (BCL)  type, Enum. Use the C# type, enum, to define new enums and use the BCL type, Enum, to implement static enum methods.

Creating an Enum

The .NET Framework BCL contains many enums and examples of how they are used.  For example, every time you put an icon on a MessageBox, you use the MessageBoxIcons enum. For a list of available enums in the BCL, look at the documentation for the Enum class and click on the Derived Classes link. 
Whenever there are situations where you are using a set of related numbers in a program, consider replacing those numbers with enums.  It will make a program more readable and type safe.  Listing 17-1 contains an enum definition and code that uses that enum in a switch statement.  Instead of using the numbers 0, 1, and 2 in the switch statement, the code is more meaningful through the use of the Volume enum.
Listing 17-1.  Creating and Using an Enum:  EnumSwitch.cs
using System;

// declares the enum
public enum Volume
{
   Low,
   Medium,
   High
}

// demonstrates how to use the enum

class
EnumSwitch
{
   static void Main()
   {
      // create and initialize
      // instance of enum type

      Volume myVolume = Volume.Medium;

      // make decision based
      // on enum value
      switch (myVolume)
      {
         case Volume.Low:
            Console.WriteLine("The volume has been turned Down.");
            break;
         case Volume.Medium:
            Console.WriteLine("The volume is in the middle.");
            break;
         case Volume.High:
            Console.WriteLine("The volume has been turned up.");
            break;
      }
      Console.ReadLine();
   }
}

Listing 17-1 contains a definition for an enum.  Notice that it is declared with the enum keyword, has a type identifier (Volume), and contains a comma separated list of values enclosed within curly braces. 
This enum is of type Volume and we use it to declare the myVolume variable in the Main method.  Since an enum is a value type, we can assign a value (Volume.Medium) to it directly, similar to the simple types such as int or double. Once the myVolume variable is declared and initialized, it is used in the switch statement. Each of the case statements represent a unique member of the Volume enum. 
Any time a member of the Volume enum is used, it is fully qualified with the "Volume" identifier to guarantee type safety.  For example, if there were a Meat enum in scope, then Meat.Medium would definitely have different semantics than Volume.Medium. With both enums in scope, it would be ambiguous to just use the Medium identifier without type qualification. Using the type identifier ensures such mistakes are not made.

Using Enums

An enum is typically specified as shown in Listing 17-1, but may be customized by changing its base type and member values. By default, the underlying type of of an enum is int. This default may be changed by specifying a specific base when declaring the enum. You would specify a different base if the enum was used extensively and there was an opportunity for space savings by selecting a smaller type. Another reason may be if you wanted the underlying type of the enum to correspond to another type in your program and you wanted to explicitly cast between the two without loss of precision. Valid base types include byte, sbyte, short, ushort, int, uint, long, and ulong.
Another modification you can make to an enum is to set the value of any enum member. By default, the first member of an enum takes the value of zero. If this value doesn't make sense for your enum, you can change it to one or some other number. Additionally, you can change any of the members of an enum to any value that is valid for its base type. Unassigned enum members have a value that is one more than their predecessor. Listing 17-2 shows how to modify the base type and member values of an enum.
Listing 17-2.  Setting the Enum Base and Initializing Members:  EnumBaseAndMembers.cs
using System;

// declares the enum
public enum Volume : byte
{
    Low = 1,
    Medium,
    High
}

class EnumBaseAndMembers
{
    static void Main()
    {
        // create and initialize
        // instance of enum type
        Volume myVolume = Volume.Low;

        // make decision based
        // on enum value
        switch (myVolume)
        {
            case Volume.Low:
                Console.WriteLine("The volume has been turned Down.");
                break;
            case Volume.Medium:
                Console.WriteLine("The volume is in the middle.");
                break;
            case Volume.High:
                Console.WriteLine("The volume has been turned up.");
                break;
        }
        Console.ReadLine();
    }
}

The Volume enum in Listing 17-2 shows how to modify the base type and members of an enum. Its base type is changed to byte with the : syntax following the enum identifier, Volume. This ensures that the Volume enum may only have members with values that are valid for type byte.
The first member of the Volume enum, Low, has its value changed to 1. The same syntax, = , may be applied to any member of the enum. You are restricted from creating forward references, circular references, and duplicate references in enum members.
The default values of the Volume enum are Low=0, Medium=1, and High=2 because the first member of an enum defaults to 0 and the following members default to one more than their predecessor. However, the Volume enum in Listing 17-2 has its Low member set to 1, which means that Medium=2 and High=3.

Enum Tricks

Enum types implicitly inherit the System.Enum type in the Base Class Library (BCL). This also means that you can use the members of System.Enum to operate on enum types. This section does just that, showing some useful tips and tricks to use with enums in your programs.
A common requirement with enums is to convert between the enum and a variable of its base type. For example, if you are getting input in the form of an int from a user or a file stream, then you can cast it to an enum and use it in a meaningful way in your program. You can also get a complete list of enum member names or enum values, which is useful if you have logic that needs to iterate through every enum member.  Listing 17-3 shows how to perform conversions between enums and their base types and how to use some of the System.Enum type members.
Listing 17-3.  Enum Conversions and using the System.Enum Type:  EnumTricks.cs
using System;

// declares the enum
public enum Volume : byte
{
    Low = 1,
    Medium,
    High
}

// shows different ways
// to work with enums
class EnumTricks
{
    static void Main(string[] args)
    {
        // instantiate type
        EnumTricks enumTricks = new EnumTricks();

        // demonstrates explicit cast
        // of int to Volume
        enumTricks.GetEnumFromUser();

        // iterate through Volume enum by name
        enumTricks.ListEnumMembersByName();

        // iterate through Volume enum by value
        enumTricks.ListEnumMembersByValue();

        Console.ReadLine();
    }

    // demonstrates explicit cast
    // of int to Volume
    public void GetEnumFromUser()
    {
        Console.WriteLine("\n----------------");
        Console.WriteLine("Volume Settings:");
        Console.WriteLine("----------------\n");

        Console.Write(@"
1 - Low
2 - Medium
3 - High

Please select one (1, 2, or 3): ");

        // get value user provided
        string volString = Console.ReadLine();
        int volInt = Int32.Parse(volString);

        // perform explicit cast from
        // int to Volume enum type
        Volume myVolume = (Volume)volInt;

        Console.WriteLine();

        // make decision based
        // on enum value
        switch (myVolume)
        {
            case Volume.Low:
                Console.WriteLine("The volume has been turned Down.");
                break;
            case Volume.Medium:
                Console.WriteLine("The volume is in the middle.");
                break;
            case Volume.High:
                Console.WriteLine("The volume has been turned up.");
                break;
        }

        Console.WriteLine();
    }

    // iterate through Volume enum by name
    public void ListEnumMembersByName()
    {
        Console.WriteLine("\n---------------------------- ");
        Console.WriteLine("Volume Enum Members by Name:");
        Console.WriteLine("----------------------------\n");

        // get a list of member names from Volume enum,
        // figure out the numeric value, and display
        foreach (string volume in Enum.GetNames(typeof(Volume)))
        {
            Console.WriteLine("Volume Member: {0}\n Value: {1}",
                volume, (byte)Enum.Parse(typeof(Volume), volume));
        }
    }

    // iterate through Volume enum by value
    public void ListEnumMembersByValue()
    {
        Console.WriteLine("\n----------------------------- ");
        Console.WriteLine("Volume Enum Members by Value:");
        Console.WriteLine("-----------------------------\n");

        // get all values (numeric values) from the Volume
        // enum type, figure out member name, and display
        foreach (byte val in Enum.GetValues(typeof(Volume)))
        {
            Console.WriteLine("Volume Value: {0}\n Member: {1}",
                val, Enum.GetName(typeof(Volume), val));
        }
    }
}

The code in Listing 17-3 includes three method calls to GetEnumFromUser, ListEnumMembersByName, and ListEnumMembersByValue.  Each of these methods demonstrate a different aspect of using System.Enum to work with enums.
The GetEnumFromUser method shows how to obtain int input and translate it to an appropriate enum type. Converting an int to an enum makes the code more readable and type safe. The following is an excerpt from Listing 17-3 that shows the pertinent part of the code that performs the conversion:
        // get value user provided
        string volString = Console.ReadLine();
        int volInt = Int32.Parse(volString);

        // perform explicit cast from
        // int to Volume enum type
        Volume myVolume = (Volume)volInt;

After the program displays a menu, it prompts the user for a selection in the form of a number (1, 2, or 3). When the user makes a selection and presses the Enter key, the code reads the value with Console.ReadLine, which returns the value as a string type. Since you can only cast an int to a Volume enum type, the user's input must be converted from a string to an int with the Int32.Parse method. Converting the int to a Volume enum type is simply a matter of applying a cast operation during assignment.
To get all the members of an enum at the same time, you can use the GetNames method of the System.Enum type, which returns a string array of the names of all an enum's members. An exerpt from the ListEnumMembersByName method in Listing 17.3 that shows this appears below:
        // get a list of member names from Volume enum,
        // figure out the numeric value, and display
        foreach (string volume in Enum.GetNames(typeof(Volume)))
        {
            Console.WriteLine("Volume Member: {0}\n Value: {1}",
                volume, (byte)Enum.Parse(typeof(Volume), volume));
        }

Because GetNames returns an array of strings, it is easy to use in a loop statement such as foreach. Something you may be curious about in the code above is the second parameter to the WriteLine method's format string. Given the enum type and a string representation of the member name, you can use the Enum.Parse method to get the underlying value of that member. Because the Volume enum's base type is byte, the return value from Enum.Parse must be cast to a byte before assignment, forcing the numeric representation of the enum value to appear.  If we would have omitted the byte cast, the output would be the Volume enum member, which would then be converted to a string representation of the member name, which is not what the code intended to show.
Instead of getting names of all the members of an enum, you may have a reason to get all the values of the enum at one time. The code below, from the ListEnumMembersByValue method in Listing 17.3, shows how to accomplish this:
        // get all values (numeric values) from the Volume
        // enum type, figure out member name, and display
        foreach (byte val in Enum.GetValues(typeof(Volume)))
        {
            Console.WriteLine("Volume Value: {0}\n Member: {1}",
                val, Enum.GetName(typeof(Volume), val));
        }

Given the type of the enum, the GetValues method of System.Enum will return an array of the given enum's base type, which in this case is byte. While iterating through this list, each member is printed to the console showing its value and name. The name is obtained by using the GetName method of System.Enum, which accepts an enum type and value for which to get the corresponding name of.

Summary

Enums are lists of strongly typed constants with members that are symbolic names, corresponding to an underlying integral type. Enum base types can be changed and member values can be specified.  The System.Enum BCL type is the base class of enum types and contains methods that allow you to work with enums in different ways, such as working with a list of names or values, converting from value to name, and converting from name to value. For more information on the System.Enum type, see the .NET Framework SDK documentation.
I invite you to return for Lesson 18: Overloading Operators.


Connecting to a SQL Server Database
ADO.Net makes connections to SQL databases very easy. Visual Studio ships with SQL Express for development, but can only be used on the local machine. SQL Server and SQL Express are essentially the same.
In this short example we create the objects necessary to connect to a SQL database, query a table, retrieve the results and display them. You may have to change the database path depending on the location, and contents, of your SQL Express sample databases. Sample databases for SQL Express can be downloaded from the Microsoft Website.
We have used the "@" symbol to denote a verbatim string, a string that is taken as is. This allows for multi line strings and we do not have to escape characters such as backslash in filenames. It also means that the connection string is more readable when separated onto multiple lines.
string connectionString = @"Data Source=.\SQLEXPRESS;
AttachDbFilename=""C:\SQL Server 2000 Sample Databases\NORTHWND.MDF"";
Integrated Security=True;Connect Timeout=30;User Instance=True";

SqlConnection sqlCon = new SqlConnection(connectionString);
sqlCon.Open();

string commandString = "SELECT * FROM Customers";
SqlCommand sqlCmd = new SqlCommand(commandString, sqlCon);
SqlDataReader dataReader = sqlCmd.ExecuteReader();

while (dataReader.Read())
{
Console.WriteLine(String.Format("{0} {1}", dataReader["CompanyName"],
dataReader["ContactName"]));
}
dataReader.Close();
sqlCon.Close();

          As we have said previously, the SqlDataReader works in connected mode,so each call to SqlDataReader.Read will stream data from the server. Itis also sequential, so once a record has been read, you can't access it again without executing the sqlCommand.ExecuteReader method again. The time between sqlCon.Open() and sqlCon.Close() there is a connection to the server. If you application opens the connection on start-up and doesn't close it until it exits you can cause unnecessary record or table locks. The way around this is by using a DataSet which will download a local copy of a subset of the main database that can be manipulated and changes sent back to the server later on.
Disconnected Mode
Disconnected mode will execute a query on the server and return the results in a DataSet object. This DataSet can then be used to display data, modify, insert or delete records without a database connection. When all changes have been made, the changes are sent back to the server.
string connectionString = @"Data Source=.\SQLEXPRESS;
AttachDbFilename=""C:\SQLServer2000SampleDatabases\NORTHWND.MDF"";Integrated Security=True;Connect Timeout=30;User Instance=True";

string commandString = "SELECT * FROM Customers";

DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(commandString, connectionString);

da.Fill(ds,"Customers"); // Customers is the name of the DataTable

foreach (DataRow dr in ds.Tables[0].Rows)
{
Console.WriteLine(String.Format("{0} {1}", dr[1].ToString(), dr[2].ToString()));
}

Database Explorer
You can also use the Database Explorer to add data elements to an application. To show the database explorer, click on the view menu and select Database Explorer or press Ctrl+Alt+S. You can add a reference to a database by creating a new connection. The process is described in more detail in the tutorial which covers Data and Windows Forms.
From the Database Explorer you can, in most cases, just drag and drop tables to a form to create a data bound grid view or control.
Updating in Connected Mode
The important thing to remember about connected mode is that updates are processed as a command is executed, whereas using disconnected methods allow the data to be previewed and further amended before being committed to the server.
Additional SQL commands must be created after the first reader has been closed, or you will have to create new objects.
string connectionString = @"Data Source=.\SQLEXPRESS;
AttachDbFilename=""C:\SQL Server 2000 Sample Databases\NORTHWND.MDF"";Integrated Security=True;Connect Timeout=30;User Instance=True";

SqlConnection sqlCon = new SqlConnection(connectionString);
sqlCon.Open();

string commandString = "SELECT * FROM Customers";
SqlCommand sqlCmd = new SqlCommand(commandString, sqlCon);
SqlDataReader dataReader = sqlCmd.ExecuteReader();

while (dataReader.Read())
{
Console.WriteLine(String.Format("{0} {1}", dataReader["CompanyName"], dataReader["ContactName"]));
}
dataReader.Close();

commandString = "UPDATE Customers SET ContactName = 'Jane Doe' WHERE CustomerID = 'ALFKI'";
sqlCmd = new SqlCommand(commandString,sqlCon);
sqlCmd.ExecuteNonQuery();

sqlCon.Close();
Updating in Disconnected Mode
Disconnected updates are processed by manipulating the DataSet object. The Rows indexers access the record and the field.
ds.Tables[0].Rows[0][2] = "Jane Doe";
          You will also need to specify and Update or Insert command to the data adaptor to instruct the server how it should update the table. Luckily there is a built in tool to help with this called the SqlCommandBuilder.

SqlCommandBuilder myBuilder = new SqlCommandBuilder(da);
da.UpdateCommand = myBuilder.GetUpdateCommand();

Changes to the DataSet are not committed to the server until the Update method is called from the DataAdaptor.
da.Update(ds, "Customers");
In the next tutorial we will look at how to use data on Windows Forms applications.