Share via


Using Indexers (C# Programming Guide) 

Indexers allow you to index a class, struct or interface in the same way as an array. For more information about using indexers with an interface, see Interface Indexers.

To declare an indexer on a class or struct, use the this keyword, as in this example:

public int this[int index]    // Indexer declaration
{
    // get and set accessors
}

Remarks

The type of an indexer and the type of its parameters must be at least as accessible as the indexer itself. For more information about accessibility levels, see Access Modifiers.

The signature of an indexer consists of the number and types of its formal parameters. It does not include the indexer type or the names of the formal parameters. If you declare more than one indexer in the same class, they must have different signatures.

An indexer value is not classified as a variable; therefore, it is not possible to pass an indexer value as a ref or out parameter.

To provide the indexer with a name that other languages can use, use a name attribute in the declaration. For example:

[System.Runtime.CompilerServices.CSharp.IndexerName("TheItem")]
public int this [int index]   // Indexer declaration
{
}

This indexer will have the name TheItem. Not providing the name attribute would make Item the default name.

Example 1

The following example shows how to declare a private array field, arr, and an indexer. Using the indexer enables direct access to the instance test[i]. The alternative to using the indexer is to declare the array as a public member and access its members, arr[i], directly.

class IndexerClass
{
    private int[] arr = new int[100];
    public int this[int index]   // Indexer declaration
    {
        get
        {
            // Check the index limits.
            if (index < 0 || index >= 100)
            {
                return 0;
            }
            else
            {
                return arr[index];
            }
        }
        set
        {
            if (!(index < 0 || index >= 100))
            {
                arr[index] = value;
            }
        }
    }
}

class MainClass
{
    static void Main()
    {
        IndexerClass test = new IndexerClass();
        // Call the indexer to initialize the elements #3 and #5.
        test[3] = 256;
        test[5] = 1024;
        for (int i = 0; i <= 10; i++)
        {
            System.Console.WriteLine("Element #{0} = {1}", i, test[i]);
        }
    }
}

Output

Element #0 = 0

Element #1 = 0

Element #2 = 0

Element #3 = 256

Element #4 = 0

Element #5 = 1024

Element #6 = 0

Element #7 = 0

Element #8 = 0

Element #9 = 0

Element #10 = 0

Notice that when an indexer's access is evaluated, for example, in a Console.Write statement, the get accessor is invoked. Therefore, if no get accessor exists, a compile-time error occurs.

Indexing Using Other Values

C# does not limit the index type to integer. For example, it may be useful to use a string with an indexer. Such an indexer might be implemented by searching for the string within the collection, and returning the appropriate value. As accessors can be overloaded, the string and integer versions can co-exist.

Example 2

In this example, a class is declared that stores the days of the week. A get accessor is declared that takes a string, the name of a day, and returns the corresponding integer. For example, Sunday will return 0, Monday will return 1 and so on.

// Using a string as an indexer value
class DayCollection
{
    string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };

    // This method finds the day or returns -1
    private int GetDay(string testDay)
    {
        int i = 0;
        foreach (string day in days)
        {
            if (day == testDay)
            {
                return i;
            }
            i++;
        }
        return -1;
    }

    // The get accessor returns an integer for a given string
    public int this[string day]
    {
        get
        {
            return (GetDay(day));
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        DayCollection week = new DayCollection();
        System.Console.WriteLine(week["Fri"]);
        System.Console.WriteLine(week["Made-up Day"]);
    }
}

Output

5

-1

Robust Programming

There are two main ways in which the security and reliability of indexers can be improved:

  • Always ensure that your code performs range and type checks when setting and retrieving values from any buffer or array accessed by the indexers.

  • Set the accessibility of the get and set accessors to be as restrictive as is reasonable. This is important for the set accessor in particular. For more information, see Asymmetric Accessor Accessibility (C# Programming Guide).

See Also

Tasks

Indexers Sample

Reference

Indexers (C# Programming Guide)
Properties (C# Programming Guide)

Concepts

C# Programming Guide