developmentor - a developer services company				  
				      C# Tutorial
   Modules

Indexers


Goals:

  • Use an indexer provided by a library class.
  • Implement several indexers of varying complexity.

Overview

Indexers provide a convenient syntax to get or set the elements of a collection. The most common indexers provide access by integer index; for example, the elements of an array, the characters in a string, or the cells of a matrix. More sophisticated indexers allow access based on other types. For example, a string index could be used by an employee directory to lookup an employee by last name.


part 1- Using an indexer - string

Indexers are relatively common in the .NET Framework library. The most visible example is probably string which offers read-only access to the characters it is storing.

steps:

  1. Write a simple program that creates a string and uses the indexer to read individual characters. The first character is at index 0, the second at index 1, etc. String provides a read-only Length property which can be used to determine the maximum allowable index. Attempt to change a character in the string using the indexer. The compiler should issue an error saying that the indexer is read-only.

Solutions:


part 2- Simple indexer - Student grades

In most U.S. schools each letter grade has a numeric equivalent, an 'A' is worth 4.0, a 'B' worth 3.0, and so on. Adding up these values and dividing by the number of courses produces the grade point average or gpa. The gpa is thus a single number that gives a measure of academic performance.

Suppose a student attending a four year university would like to track their scholastic performance each year. The student would simply need to keep four gpa values, one for each year. In this exercise we will code a student class that stores the four gpa numbers and provides a read-write indexer to access the values.

steps:

  1. Create a Student class. Add a private array of double to store the four gpas.

  2. Add a read-write indexer for the gpa values. Use the year as the index: 1 for the first year, 2 for the second year, and so on. Be careful to map the year to the array index: the year will be 1-4 while the array storing the gpa values is zero based. Simply subtract 1 from the year to get an appropriate index. The trickiest part to the implementation is how to react to an invalid index. The real solution would probably be to throw an exception, but since we have not yet covered exceptions we have to be content with a less sophisticated approach: in the get accessor, print an error message and return -1, in the set accessor, print and error message and return without performing the requested assignment.

    class Student
    {
    	public double this[int year]
    	{
    		get
    		{
    			...
    		}
    
    		set
    		{
    			...
    		}
    	}
    }
    
  3. Create a Main program and test your work.

Solutions:


part 3- Sophisticated indexer - photo album (optional)

An album is a group of photos. Since an album can be viewed as a collection it is a reasonable candidate for an indexer to provide access to its underlying parts. In this case we will provide two different indexers for the photos contained in the album: a read-write indexer to access photos by integer index and a read-only indexer to access photos by title.

The trickiest part of this implementation is how to react to failure, i.e. when the user provides an invalid index or a title that is not found among the photos. The set accessor is easy to deal with since we can simply refuse to perform the requested assignment. The get accessor should just return null if the requested photo is not found. In production code we might want to use an exception to notify the user if either access method fails.

steps:

  1. Create a class Photo to represent a photograph. A realistic photograph class might store a title, description, creation date, link to a disk file containing the image, etc. For our purposes we will keep things simple and store only a title. When implementing the Photo class use standard practices: store the data in a private field, provide a public property to access the data, and a constructor to do initialization.

    class Photo
    {
    	...
    }
    
  2. Create a class Album to hold the photographs. Store the photographs in an array of Photo. Write a constructor that takes an integer capacity and allocates an array of the requested size.

    class Album
    {
    	Photo[] photos;
    
    	public Album(int capacity)
    	{
    		...
    	}
    	...
    }
    
  3. Add a read-write indexer to the Album class that gives access to the underlying array of photos. The return type of the indexer will be Photo and the parameter an int. Perform validation on the index to ensure it is within range.

    class Album
    {
    	public Photo this[int index]
    	{
    		get
    		{
    			...
    		}
    
    		set
    		{
    			...
    		}
    	}
    	...
    }
    
  4. Add a read-only indexer to the Album class that gives access to the underlying array of photos by title. The return type of the indexer will be Photo and the parameter a string. Use the == operator to compare the title the user is looking for with the title of each photo in the array.

    class Album
    {
    	public Photo this[string title]
    	{
    		get
    		{
    			...
    		}
    	}
    	...
    }
    
  5. Create a Main program and test your work.

Solutions:

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