English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# Indexers (Indexer)

An indexer is a special property that allows access to a class or structure as if it were an array of its internal collection. C# allows us to define custom indexers, generic indexers, and overloaded indexers.

Indexers can be defined using properties with the this keyword and square brackets [].

Syntax

<return type> this[<parameter type> index]
{ 
   get {
        // Return the value at the specified index from the internal collection
    }
   set { 
       // Set the value at the specified index within the internal collection
    }
}

Define an indexer

The following example defines an indexer within a class.

class StringDataStore
{
    private string[] strArr = new string[10]; // Internal Data Storage
    public string this[int index]
    {
        get
        {
            if(index < 0 || index >= strArr.Length)
                throw new IndexOutOfRangeException("Index out of range");
                return strArr[index];
        }
        set
        {
            if (index < 0 || index >= strArr.Length)
                throw new IndexOutOfRangeException("Index out of range");
            strArr[index] = value;
        }
    }
}

The StringDataStore class defines an indexer for its private array strArr. Now, you can use StringDataStore to add and retrieve string values from strArr as if it were an array, as shown below.

StringDataStore strStore = new StringDataStore();
strStore[0] = "One";
strStore[1] = "Two";
strStore[2] = "Three";
strStore[3] = "Four";
        
for (int i = 0; 10 ; i++)
    Console.WriteLine(strStore[i]);
Output:
One
Two
Three
Four

From C# 7Starting, you can use expression-bodied syntax for get and set.

class StringDataStore
{
    private string[] strArr = new string[10]; // Internal Data Storage
    public string this[int index]
    {
        get => strArr[index];
        set => strArr[index] = value;
    }
}

Generic Indexer

Indexers can also be generic. The following generic class includes a generic indexer.

class DataStore<T>
{
    private T[] store; 
    public DataStore()
    {
        store = new T[10];
    }
    public DataStore(int length)
    {
        store = new T[length];
    }
    public T this[int index]
    {
        get
        {
            if (index < 0 && index >= store.Length)
                throw new IndexOutOfRangeException("Index out of range");
                return store[index];
        }
        set
        {
            if (index < 0 || index >= store.Length)
                throw new IndexOutOfRangeException("Index out of range");
            store[index] = value;
        }
    }
    public int Length
    {
        get
        {
            return store.Length;
        }
    }
}

The generic indexer can be used with any data type. The following example demonstrates the usage of the generic indexer.

DataStore<int> grades = new DataStore<int>();
grades[0] = 100;
grades[1] = 25;
grades[2] = 34;
grades[3] = 42;
grades[4] = 12;
grades[5] = 18;
grades[6] = 2;
grades[7] = 95;
grades[8] = 75;
grades[9] = 53;
for(int i = 0; i < grades.Length;i++)
    Console.WriteLine(grades[i]);
DataStore<string> names = new DataStore<string>(5);
names[0] = "Steve";
names[1] = "Bill";
names[2] = "James";
names[3] = "Ram";
names[4] = "Andy";
for(int i = 0; i < names.Length;i++)
    Console.WriteLine(names[i]);

Overload Indexers

Indexes can be overloaded with different data types. The following example demonstrates the overloading of indexers with int type and string type indexes.

class StringDataStore
{
    private string[] strArr = new string[10]; // Internal Data Storage
    // Integer Type Indexer
    public string this[int index]
    {
        get
        {
            if(index < 0 || index >= strArr.Length)
                throw new IndexOutOfRangeException("Index out of range");
            return strArr[index];
        }
        set
        {
            if(index < 0 || index >= strArr.Length)
                throw new IndexOutOfRangeException("Index out of range");
            strArr[index] = value;
        }
    }
    // String Type Indexer
    public string this[string name]
    {
        get
        {
            foreach(string str in strArr){
                if(str.ToLower() == name.ToLower())        
                    return str;
                }
                    
            return null;
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        StringDataStore strStore = new StringDataStore();
        strStore[0] = "One";
        strStore[1] = "Two";
        strStore[2] = "Three";
        strStore[3] = "Four";
        
        Console.WriteLine(strStore["one"]);
        Console.WriteLine(strStore["two"]);
        Console.WriteLine(strStore["Three"]);
        Console.WriteLine(strStore["Four"]);
    }
}
Note: Indexers do not allow ref and out parameters.