
.NET 1.1+C# Indexers (2)
The thirteenth part of the C# Object-Oriented Programming tutorial describes the use of indexers. A class that has an indexer can be used in a similar manner to an array. Objects of the class can use array-style notation to present multiple values.
Adding the Constructor
The constructor for the new class will accept two integer parameters that define the upper and lower boundaries. These values will be stored in the two associated class variables. Using these boundaries the length of the underlying array can be calculated and the _items array can be initialised accordingly.
To create the constructor, add the following code to the class:
public MyArray(int lowerBound, int upperBound)
{
_lowerBound = lowerBound;
_upperBound = upperBound;
_items = new string[1 + upperBound - lowerBound];
}
NB: To simplify this example validation checks have been omitted. In a real program you would want to validate that the upper boundary is larger than the lower boundary. Other validation checks in the code below have also been removed for clarity.
Adding the Indexer
Now that the preparation work is complete we can add the indexer to the class. For this simple array-like class the indexer accepts a single integer parameter containing the index of the string that is being read from or written to. This index needs to be adjusted to correctly map to the underlying data before returning the value from the array or writing the new value into the array.
The code to add the indexer is shown below. Note that, as with property declarations, the set accessor uses the 'value' variable to determine the value that has been assigned by the calling function:
public string this[int index]
{
get { return _items[index - _lowerBound]; }
set { _items[index - _lowerBound] = value; }
}
Testing the MyArray Class
The new class can be tested using the Main method of the program. Open the Program class and add the following code to create a new instance of MyArray and to populate it with values.
static void Main(string[] args)
{
MyArray fruit = new MyArray(-2, 1);
fruit[-2] = "Apple";
fruit[-1] = "Orange";
fruit[0] = "Banana";
fruit[1] = "Blackcurrant";
Console.WriteLine(fruit[-1]); // Outputs "Orange"
Console.WriteLine(fruit[0]); // Outputs "Banana"
}
Creating a Multidimensional Indexer
Syntax
Indexers are not limited to a single dimension. By including more than one index variable in the square brackets of the indexer declaration, multiple dimensions may be added. For example, to declare a two-dimensional indexer the syntax is as follows:
public data-type this[index-type1 index-name1, index-type2 index-name2]
{
get {}
set {}
}
It is also possible to overload indexers is a similar manner to overloading methods. Several declarations for this[] can be included each with a different set of parameters, or signature. We can demonstrate this by adding a second indexer to the MyArray class. This time the indexer will have two integer parameters. The first will determine which item from the private array will be looked up. The second parameter will determine a position within the string and return the character at that position. For simplicity the following code creates an overloaded read-only indexer.
public string this[int word, int position]
{
get { return _items[word - _lowerBound].Substring(position, 1); }
}
To test the second indexer, modify the Main method as follows:
static void Main(string[] args)
{
MyArray fruit = new MyArray(-2, 1);
fruit[-2] = "Apple";
fruit[-1] = "Orange";
fruit[0] = "Banana";
fruit[1] = "Blackcurrant";
Console.WriteLine(fruit[-1, 0]); // Outputs "O"
Console.WriteLine(fruit[0, 2]); // Outputs "n"
}
16 January 2008