Monday 19 December 2011

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.
Note: 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. If the code had not appended base("From Derived") to the Derived constructor, the code would have automatically called Parent(). 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 and explicitly states your intention that you don't want polymorphism to occur. 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 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 an instance of 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 <classname>.<static class member>. 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.
Note: You've probably noticed the use of the public modifier (an access modifier), meaning that a class member can be accessed from other classes. When used on a class, it means that the class can be accessed by DLLs outside of the Assembly (which is commonly a *.exe or *.dll file). Lesson 19: Encapsulation discusses access modifiers in more depth.
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 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. For example, if you created a class named Console, you would need to put it in your own namespace to ensure that there wasn't any confusion about when the System.Console class should be used or when your class should be used. Generally, it would be a bad idea to create a class named Console, but in many cases your classes will be named the same as classes in either the .NET Framework Class Library or a third party library and namespaces help you avoid the problems that identical class names would cause.
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 myPrint1. Main() calls this method with the fully qualified name of tutorial.myExample1.myPrint1(). 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 call 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 call 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:
  • Classes
  • Structures
  • Interfaces
  • Enumerations
  • Delegates
Future chapters 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 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 parentheses are empty, no information will be transferred to 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 class 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.
As you know, methods have return values, but sometimes you'll want to return more than one value from a method. An out parameter allows you to return additional values from a method.
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. When calling viewAddresses(), we pass in four string arguments. The number of arguments is variable and will be converted to a string[] automatically. In viewAddresses() we use a foreach loop to print each of these strings. Instead of the list of string arguments, 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 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 (<boolean expression>) { <statements> }. 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 { <statements> } while (<boolean expression>);. 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 statements 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 appropriate when you know exactly how many times you want to perform the statements within the loop. The contents within the for loop parentheses hold three sections separated by semicolons (<initializer list>; <boolean expression>; <iterator list>) { <statements> }.
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. The purpose of the program is to  print only odd numbers less than 10.
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 (<type> <iteration variable> in <list>) { <statements> }. 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 iteration variable 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. You learned about arrays in Lesson 02: Operators, Types, and Variables. You can also iterate over C# generic collections also, described in Lesson 20: Introduction to Generic Collections.
While iterating through the items of a list with a foreach loop, the list is read-only. This means that you can't modify the iteration variable within a foreach loop. There is a subtlety here; Later, you'll learn how to create custom types, called class and struct, that can contain multiple fields.  You can change the fields of the class or struct, but not the iteration variable for the class or struct itself in 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 iteration 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 foreach loop.
In the foreach loop, we've used a string variable, 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, the Console.WriteLine method will 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, do, 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