developmentor - a developer services company				  
				      C# Tutorial
   Modules

Reference Types


Goals:

  • Create a reference/array pair.
  • Make a class with a reference field.
  • Pass a reference as a parameter.
  • Practice with an array of references.

Overview

In this lab we create a beehive simulation that demonstrates the key features of reference types. There will be three main classes involved: Hive, Bee, and Keeper. In addition there will be a simple test class called Driver with a Main method to get the simulation started.


part 1- Hive

We begin the simulation with a class to represent the beehive. The main job of the hive is to contain the cells in which the nectar ferments and becomes honey.

steps:

  1. Create a class Hive. Add a Cells field to represent the cells: the field should be a reference to an array of int and should be public to allow the access by the bees. Note that the field is just an array reference, there is not array at this point.

    class Hive
    {
    	...
    }
    

  2. Define two public integer constants Empty and Full to indicate the state of each cell. Note the use of the keyword const to create symbolic constants whose value cannot be changed.

    class Hive
    {
    	public const int Empty = 0;
    	public const int Full  = 1;
    	...
    }
    

  3. Write a constructor for Hive. The constructor should take an integer argument specifying the number of cells the hive should contain. Allocate an array of the requested size using new and store the array in the Cells field. Initialize each cell to Empty.

    class Hive
    {
    	public Hive(int size)
    	{
    		...
    	}
    	...
    }
    


part 2- Bee

Next we need a class to represent the bee. The bee's job is to go out into the countryside, gather nectar, return to the hive, and deposit the nectar into an empty cell.

steps:

  1. Create the Bee class.

    class Bee
    {
    	...
    }
    

  2. We will need some randomization to make the simulation interesting. Add the following simple random number generator to the Bee class. The Next method of the Random class takes an int argument called the bound and returns a random number between 0 and bound-1. The Random class is part of the standard library.

    class Bee
    {
    	private Random random = new Random();
    	...
    }
    

  3. The bee's job is to search for nectar, gather the nectar, return to the hive, and deposit the nectar in one of the cells.  Thus, the bee is always in one of four states: searching, gathering, returning, or depositing. Add symbolic integer constants for each of the four states and a integer field that records the current state.  The constants and the state field will only be needed inside the bee class so they can be private.

  4. A bee lives in a hive. To model this, add a Hive reference as a field of the bee class. Note that this field is not a hive embedded inside the bee, it is simply a reference to a hive that exists outside of the bee.

  5. Add a constructor to the bee class. The construction should take a Hive reference as a parameter. Inside the constructor set the bee's hive field to the parameter hive and set the bee's state to searching.

    class Bee
    {
    	public Bee(Hive hive)
    	{
    		...
    	}
    	...
    }
    

  6. The bee work algorithm is concisely captured using a state machine. A bee is in one of four states: searching, gathering, returning and depositing. During each time period, each bee performs work depending on its current state. When searching, a bee has a one in five chance of finding a flower with nectar. If nectar is found, the bee starts gathering. If nectar is not found, the bee continues searching.  It takes one time unit for a bee to gather the nectar, then it returns to the hive.  It takes one time unit for a bee to return to the hive, then it deposits the nectar in a cell.  In order to deposit the nectar the bee must find an empty cell.  The bee chooses a cell at random and checks if the cell is empty. If the cell is empty, the bee fills it and then begins searching again.  If the cell is full, the bee keeps looking for an empty cell. The bee uses its hive reference field to access the hive of which it is a member. This is captured by the following Work method. Feel free to use this method in your program or to code it yourself.

    class Bee
    {
    	public void Work()
    	{
    		switch (state)
    		{
    			case Searching:
    			{
    				Console.Write("S");
    			
    				if (random.Next(5) == 0)
    					state = Gathering;
    
    				break;
    			}
    			case Gathering:
    			{
    				Console.Write("G");
    			
    				state = Returning;
    
    				break;
    			}
    			case Returning:
    			{
    				Console.Write("R");
    
    				state = Depositing;
    
    				break;
    			}
    			case Depositing:
    			{
    				Console.Write("D");
    			
    				//
    				// choose random cell to deposit
    				//
    				int i = random.Next(hive.Cells.Length);
    			
    				if (hive.Cells[i] == Hive.Empty)
    				{
    					hive.Cells[i] = Hive.Full;
    					state = Searching;
    				}
    
    				break;
    			}
    		}
    	}
    	...
    }
    


part 3- Keeper

The bee keeper will run the simulation. The keeper will create the hive, create the bees, call the bee's Work method, and periodically collect the honey from the hive.

steps:

  1. Create the Keeper class.

    class Keeper
    {
    	...
    }
    

  2. Add a method to Keeper to collect all the nectar from a hive. The method takes a Hive parameter, counts the number of filled cells inside the hive, sets all the cells to empty, and returns the count of the number of filled cells. Notice that the parameter is a reference so any changes made to the parameter will be visible back in the calling code.

    class Keeper
    {
    	public int Collect(Hive hive)
    	{
    		...
    	}
    	...
    }
    

  3. Add a Run method to the keeper class.

    class Keeper
    {
    	public void Run()
    	{
    		...
    	}
    }
    

  4. Inside Run, create a hive with 20 cells.

  5. Inside Run, create an array of Bee references. Note that creating an array of a reference type creates an array of references and not an array of objects. When the Bee array is created we get an array of Bee references all initialized to null - at this point we have no Bee objects. Next, loop through the array and create a Bee object for each slot in the array. Pass the Hive into the Bee constructor as you create each bee.

    class Keeper
    {
    	public void Run()
    	{
    		...
    		//
    		// array of 5 Bee references - no Bee objects here
    		//
    		Bee[] bees = new Bee[5];
    		...
    	}
    }
    

  6. Add the following control code to the Run method. Notice how the bees work for a while and then the keeper collects the honey and the cycle begins again.

    class Keeper
    {
    	public void Run()
    	{
    		...
    		while (true)
    		{
    			for (int i = 0; i < 20; i++)
    			{
    				for (int j = 0; j < bees.Length; j++)
    					bees[j].Work();
    			}
    
    			Console.WriteLine("collect {0}", Collect(hive));
    		}
    	}
    }
    


part 4- Driver

Here we add a simple driver class to start the simulation.

steps:

  1. Create a class Driver with a Main method. Inside Main, create a Keeper and call its Run method.

    	class Driver
    	{
    		static void Main()
    		{
    			Keeper keeper = new Keeper();
    
    			keeper.Run();
    		}
    	}
    

Solutions:

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