developmentor - a developer services company				  
				      C# Tutorial
   Modules

Class


Goals:

  • Write a class that demonstrates various common coding patterns.
  • Use instance fields to store state.
  • Use instance methods to manipulate and report state.
  • Apply access modifiers as appropriate.
  • Practice with the various parameter passing mechanisms.

Overview

A class is the primary unit of code in C#. A class defines a new type that models some aspect of the 'real' world. In this activity, we will write code that demonstrates a few of the most common coding patterns for classes. We will also explore the various ways parameters can be passed to methods.


part 1- Point

Here we will implement a class to model a two dimensional point. The point class will provide a good example of the most common type of class: instance fields store the state of an object and methods implement the behavior of the class by manipulating and reporting the state.

steps:

  1. Create a new project in Visual Studio 2010 for the point exercise.

  2. Create a class called Point to represent a two dimensional point.

    class Point
    {
      ...
    }
    
  3. Add two instance fields to store the state of the point. The fields are private since we only want code in the Point class to access them. Users will be forced to go through the public interface that we will add shortly.

    private int x; // x coordinate
    private int y; // y coordinate
    
  4. Implement the following Initialize method to load the passed values into the private fields.

    public void Initialize(int x, int y)...
    
  5. Implement public get and set "access methods" for the x and y coordinates. The practice of making the data private and providing public access methods is relatively common in object oriented programming.

    public void SetX(int x) ...
    public void SetY(int y) ...
    
    public int GetX() ...
    public int GetY() ...
    
  6. Implement a public Translate method to move the point by the given x and y offsets. The implementation is simple: each offset only needs to be added to the corresponding coordinate.

    public void Translate(int xOffset, int yOffset) ...
    

  7. Implement a public Scale method to move the point to a new location. The new coordinates are obtained by multiplying the old coordinates by the specified scale value. This operation may seem odd, but it actually has a nice geometric interpretation: it corresponds to moving the point to a different place on the line connecting the point and the origin.

    public void Scale(int a) ...
    
  8. Implement a public Distance method to compute the distance between the current point and the parameter.

    public double Distance(Point p) ...
    

    Recall that the formula for the distance between points is:

    square root((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    You can use the Math.Sqrt method to compute the square root.

  9. Code a Driver class with a Main method to test your work.

Solutions:


part 2- Parameter passing (optional)

C# offers three ways to pass a parameter to a method: value, ref, out.

steps:

  1. Create a new project in Visual Studio 2010 for the parameter passing exercise. Create a simple class called ParameterTest to hold the parameter test code.

  2. Write a method called Value that takes a single integer by value. Because the parameter is passed by value, any changes made inside the method affect only a local copy and will be lost when the method ends.

    public void Value(int x)
    {
    	...
    }
    

    Create a class called Driver and add a Main method to it. Create a ParameterTest object and call the Value method and verify that it behaves as expected.

  3. Write a method called Swap that takes a takes two integers by reference and swaps their values. Call the method and verify that the changes made inside the method are visible after the call. Note that the keyword ref is required in both the parameter definition and in the method call. Reference parameters are sometimes called "in out" parameters because a value goes in and comes out of the method. Since a value is being passed in, the compiler requires that a variable passed as a reference parameter already be initialized. Verify this behavior by attempting to pass an uninitialized variable as a reference parameter.

    public void Swap(ref int a, ref int b)
    {
    	...
    }
    
  4. Write a method called MinMax that takes a takes an array of integers and two out parameters. Locate both the minimum and maximum values in the array and assign them to the out parameters in order to return both values to the calling code. Call the method and verify that data is being returned through the parameters.

    public void MinMax(int[] a, out int min, out int max)
    {
    	...
    }
    

Solutions:


part 3- Variable length parameter list (optional)

C# supports variable length parameter lists. A variable length parameter is declared by putting the keyword params on a one dimensional array. The caller can then pass any number of arguments and the compiler creates an array and loads it with the passed values. There are a few restrictions: the variable parameter must be the last argument and it can only be applied to a one dimensional array. An example is shown below with one regular parameter and a variable length parameter. Users calling the method pass a string argument followed by zero or more integers.

void Process(string prefix, params int[] values)
{
	//...
}

void Test()
{
	Process("data");                         // zero ints
	Process("data", 1);                      // one int
	Process("data", 1, 2, 3);                // three ints
	Process("data", new int[] {1, 2, 3, 4}); // explicit array ok too
}

steps:

  1. Write a method called Sum that uses the params technique to take a variable number of integers, compute their sum, and return the result.

Solutions:


part 4- Robot (optional)

Here we will create a class to model a simple robot. The robot will have a name, a location in a two dimensional world, and will record the compass direction it is facing. The Robot will begin with only simple behavior: initialization and printing of its state. More complex abilities such as moving and turning will be added as the exercise progresses.

steps:

  1. Create a new project in Visual Studio 2010 for the robot exercise.

  2. Create a class called Robot to represent a robot.

    class Robot
    {
      ...
    }
    
  3. Add four instance fields to store the state of the robot. The fields are private since we only want code in the Robot class to access them. Users will be forced to go through the public interface that we will add shortly.

    private string name;
    private int    x;
    private int    y;
    private int    direction;
    
  4. Next we need to model the compass directions North, East, South, and West. There are many ways this can be done in C#. We will choose the simplest option and define a public integer field for each direction. These values can be assigned to the direction field to indicate the direction the robot is facing. We will make this a bit more realistic by introducing the C# keyword const to mark the directions as constants. Adding const makes our code more logically correct since we are creating symbolic constants. Later we will see other options for creating symbolic constants.

    public const int North = 0;
    public const int East  = 1;
    public const int South = 2;
    public const int West  = 3;
    
  5. Add an implementation of the following Initialize method. The method should set each field to the corresponding value passed as a parameter.

    public void Initialize(string name, int x, int y, int direction)
    {
      ...
    }
    
  6. Add an implementation of the following Print method. The method should print the current state of the robot (name, x, y, and direction) to the console.

    public void Print()
    {
      ...
    }
    

    When printing the direction, a function such as the following might be convenient to map from the internal integer representation to a human readable string. Note that the position in the array of each string corresponds to the value for the constants, so the string "North" is in the first position since the value of the constant North is 0. The method is private since it is for the exclusive use of the Robot class.

    private string ToString(int direction)
    {
    	string[] names = { "North", "East", "South", "West" };
    
    	return names[direction];
    }
    
  7. Create a class called World containing a Main method. Inside Main, create a Robot and call the Initialize and Print methods to test your work.

  8. We will now add some more interesting behavior to the Robot class beginning with a method called Move. The Move method will move the robot forward one unit in the direction it is currently facing. For example, if the robot is currently at position (0,0) and is facing north, calling Move will move the robot one unit in the positive y direction (i.e. North) so the robot will then be at position (0,1). Implement the following public Move method for the Robot class. Call Move from Main to test your work.

    public void Move()
    {
      ...
    }
    
  9. Next we add the ability for the robot to turn either left or right. Turning the robot modifies the direction the robot is facing. For example, if the robot is currently facing north and turns left, the robot would then be facing west.

    Add two symbolic constants to represent Left and Right.

    public const int Left  = 4;
    public const int Right = 5;
    

    Modify the ToString method so it works with the new constants.

    private string ToString(int direction)
    {
    	string[] names = { "North", "East", "South", "West", "Left", "Right" };
    
    	return names[direction];
    }
    

    Implement the following public Turn method. The parameter to is used to indicate whether the turn is to the Left or to the Right. Call Turn from Main to test your work.

    public void Turn(int to)
    {
      ...
    }
    
  10. We will now add a random number generator to the Robot. The .NET Framework class library provides a class named System.Random that will do the work for us.

    Add the following field to the robot simulation. Notice how the generator uses the current time as the seed to ensure a different sequence of random numbers each time the program is run.

    private Random random = new Random((int)DateTime.Now.Ticks);
    

    Add a method called Step to the Robot class which makes use of the random number generator. The generator offers a method named Next which takes an int parameter (called the bound) and returns a random number between 0 and bound-1. The step method should choose randomly between moving and turning. A reasonable probability distribution might be a 50% chance for Move(), a 25% chance for Turn(Left), and a 25% chance for Turn(Right). Notice that calling Next(2) on the random number generator has an even probability of returning 0 or 1 thus providing a convenient way to create a 50/50 chance. Call Step from Main to test your work.

    public void Step()
    {
      ...
    }
    
  11. Here we have the robot search for a goal. The goal is simply an (x,y) coordinate pair. To keep the simulation from running indefinitely we will define a "world size" and restrict the robot's movement to coordinates in the valid range. Add the following constant to the Robot class.

    public const int Size = 10;
    

    Modify the Move method to keep the coordinates in the range 0 through Size-1. The following code accomplishes this very concisely.

    public void Move()
    {
    	...
    	//
    	// force coordinates back into valid range
    	//
    	x = (x + Size) % Size;
    	y = (y + Size) % Size;
    }
    

    Add a method called At to the Robot class that determines whether the robot is at the given coordinates. This method will be useful to test whether the robot has reached the goal.

    public bool At(int x, int y)
    {
    	...
    }
    

    Hardcode an (x,y) coordinate pair in the Main method to serve as the goal.

    int goalx = 5;
    int goaly = 5;
    

    Repeatedly call Step on the robot until it reaches the goal. Use the At method to determine if the robot is at the goal. You may also want to create several robots and have them compete to find the goal.

Solutions:

This material is excerpted from the Programming C# course offered by DevelopMentor.