Indexers in C#

1. Indexing with an Integer Index

A class that contains a database row might implement an indexer to access the columns in the row:

using System; using System.Collections; class DataValue {

public DataValue(string name, object data)

{

this.name = name;

this.data = data;

}

public string Name {

get

{

return(name);

}

set

{

name = value;

}

}

public object Data {

get

{

return(data);

}

set

{

data = value;

}

}

string name; object data;

}

class DataRow {

public DataRow()

{

row = new ArrayList();

}

public void Load()

{

/* load code here */

row.Add(new DataValue(“Id”, 5551212));

row.Add(new DataValue(“Name”, “Fred”));

row.Add(new DataValue(“Salary”, 2355.23m));

}

// the indexer (use -1 because column index is 1-based)

public DataValue this[int column]

{

get

{

return((DataValue) row[column – 1]);

}

set

{

row[column – 1] = value;

}

}

ArrayList row;

}

class Test {

public static void Main()

{

DataRow row = new DataRow();

row.Load();

Console.WriteLine(“Column 0: {0}”, row[1].Data);

row[1].Data = 12;           // set the ID

}

}

The DataRow class has functions to load a row of data, has functions to save the data, and has an indexer function to provide access to the data. In a real class, the Load() function would load data from a database.

You write the indexer function the same way you write a property, except the indexer function takes an indexing parameter. You declare the indexer using the name this since it has no name.

2. Indexing with a String Index

A class can have more than one indexer. For the DataRow class, it might be useful to be able to use the name of the column for indexing:

using System;

using System.Collections;

class DataValue {

public DataValue(string name, object data)

{

this.name = name;

this.data = data;

}

public string Name {

get

{

return(name);

}

set

{

name = value;

}

}

public object Data {

get

{

return(data);

}

set

{

data = value;

}

}

string name;

object data;

}

class DataRow {

public DataRow()

{

row = new ArrayList();

}

public void Load()

{

/* load code here */

row.Add(new DataValue(“Id”, 5551212));

row.Add(new DataValue(“Name”, “Fred”));

row.Add(new DataValue(“Salary”, 2355.23m));

}

public DataValue this[int column]

{

get

{

return( (DataValue) row[column – 1]);

}

set

{

row[column – 1] = value;

}

}

int FindColumn(string name)

{

for (int index = 0; index < row.Count; index++)

{

DataValue dataValue = (DataValue) row[index];

if (dataValue.Name == name)

return(index + 1);

}

return(-1);

}

public DataValue this[string name]

{

get

{

return( (DataValue) this[FindColumn(name)]);

}

set

{

this[FindColumn(name)] = value;

}

}

ArrayList row;

}

class Test {

public static void Main()

{

DataRow row = new DataRow(); row.Load();

DataValue val = row[“Id”];

Console.WriteLine(“Id: {0}”, val.Data);

Console.WriteLine(“Salary: {0}”, row[“Salary”].Data);

row[“Name”].Data = “Barney”; // set the name Console.WriteLine(“Name: {0}”,

row[“Name”].Data);

}

}

The string indexer uses the FindColumn() function to find the index of the name and then uses the int indexer to do the proper thing.

3. Indexing with Multiple Parameters

Indexers can have more than one parameter to simulate a multidimensional virtual array. The following example illustrates such a use:

using System;

public class Player {

string name;

public Player(string name)

{

this.name = name;

}

public override string ToString()

{

return(name);

}

}

public class Board {

Player[,] board = new Player[8, 8];

int RowToIndex(string row)

{

string temp = row.ToUpper();

return((int) temp[0] – (int) ‘A’);

}

int PositionToColumn(string pos)

{

return(pos[1] – ‘0’ – 1);

}

public Player this[string row, int column]

{

get

{

return(board[RowToIndex(row), column – 1]);

}

set

{

board[RowToIndex(row), column – 1] = value;

}

}

public Player this[string position]

{

get

{

return(board[RowToIndex(position),

PositionToColumn(position)]);

}

set

{

board[RowToIndex(position),

PositionToColumn(position)] = value;

}

}

}

class Test

{

public static void Main()

{

Board board = new Board();

board[“A”, 4] = new Player(“White King”);

board[“H”, 4] = new Player(“Black King”);

Console.WriteLine(“A4 = {0}”, board[“A”, 4]);

Console.WriteLine(“H4 = {0}”, board[“H4”]);

}

}

The example implements a chessboard that can be accessed using standard chess notation (a letter from A to H followed by a number from 1 to 8). The first indexer accesses the board using string and integer indices, and the second indexer uses a single string such as “C5.”

Source: Gunnerson Eric, Wienholt Nick (2005), A Programmer’s Introduction to C# 2.0, Apress; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *