Wednesday, June 10, 2026

C# Indexer Explained for Beginners

Understanding Indexers in C#

When learning C#, you often use properties to expose fields of a class. However, when a class contains multiple values that can be accessed using an index, C# provides a special feature called an Indexer.
An indexer allows an object to be used in the same way as an array.

What Is an Indexer?

An Indexer is a parameterized property. It allows objects of a class to be accessed using square brackets ([]) just like arrays.
For example:
  • The object of Customer class with index 0 will be customer[0] will refer to a field of Customer class.
  • The object of Employee class with index 2 will be employee[2] will refer to a field of Employee class.

Instead of calling a method such as: customer.GetValue(0); an indexer provides a more natural syntax.

Characteristics of an Indexer

  1. An indexer is a parameterized property.
  2. Unlike ordinary properties, an indexer has no name. It is represented by the keyword this followed by square brackets containing one or more parameters.
  3. A property is generally used to expose a single field, whereas an indexer is commonly used to expose a collection of values or multiple related values.
  4. An indexer contains get and set accessors just like a property.
  5. The get accessor returns a value based on the supplied index.
  6. The set accessor stores a value at the supplied index.
  7. You can use local variables, if statements, switch statements, loops, and other logic inside an indexer.
  8. Indexer parameter i.e. index need not necessarily be an integer; it can be integer, boolean or string type etc.
  9. Indexer return type must match the return type of the fields which it can deal with for get and set operations.

Example 1: Using an Indexer to Access Multiple Fields

Suppose a Customer class contains three fields: Id, Age, and Salary. An indexer can be used to access them through index positions.

public class Customer
{
    private int _id;
    private int _age;
    private int _salary;

    public int this[int index]
    {
        get
        {
            switch (index)
            {
                case 0: return _id;
                case 1: return _age;
                case 2: return _salary;
                default:
                    throw new Exception("The index can be 0, 1 or 2");
            }
        }
        set
        {
            switch (index)
            {
                case 0: _id = value; break;
                case 1: _age = value; break;
                case 2: _salary = value; break;
            }
        }
    }
} 
class Program
{
    static void Main(string[] args)
    {
        Customer customer = new Customer();

        customer[0] = 100;
        customer[1] = 32;
        customer[2] = 50000;

        Console.WriteLine(
            $"The id, age and salary are " +
            $"{customer[0]}, {customer[1]} and {customer[2]} respectively.");
    }
} 

Output
The id, age and salary are 100, 32 and 50000 respectively.

How It Works

Here the index positions represent different fields:

IndexField
0Id
1Age
2Salary

  • When customer[1] is executed, the get accessor runs and returns _age.
  • When customer[1] = 32 is executed, the set accessor runs and stores the value in _age.

Another example to access different fields of a class using indexer is as follows. In this example, indexer returns string type data for an index.

Example 2: Using an Indexer to Access Multiple Fields

public class Employee
{
    private string _name;
    private string _city;
    private string _designation;

    public string this[int index]
    {
        get
        {
            switch (index)
            {
                case 0: return "The name of Employee is " + _name;
                case 1: return "The city of Employee is " + _city;
                case 2: return "The designation of Employee is " + _designation;
                default: throw new Exception("The index can be 0, 1 or 2"); //return -1;
            }
        }
        set
        {
            switch (index)
            {
                case 0: _name = value; break;
                case 1: _city = value; break;
                case 2: _designation = value; break;
            }
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        Employee employee = new Employee();
        employee[0] = "Ajeet";
        employee[1] = "Delhi";
        employee[2] = "Software Engineer";
        Console.WriteLine($"{employee[0]}\n{employee[1]}\n{employee[2]}");
    }
} 

Example 3: Using an Indexer with an Array

A more common use of indexers is to expose a collection such as an array.

public class Customer
{
    public string[]? Names = null;

    public string this[int index]
    {
        get
        {
            if (Names != null &&
                index >= 0 &&
                index < Names.Length)
            {
                return Names[index];
            }

            return "Unknown";
        }
        set
        {
            if (Names != null &&
                index >= 0 &&
                index < Names.Length)
            {
                Names[index] = value;
            }
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Customer customer = new Customer();

        customer.Names = new string[]
        {
            "John",
            "Jane",
            "Doe"
        };

        Console.WriteLine(customer[0]);
        Console.WriteLine(customer[1]);
        Console.WriteLine(customer[2]);
    }
} 

Output
John
Jane
Doe

How It Works

The class contains an array called Names. The indexer uses the supplied index to access an element of the array: customer[0] is internally handled by: Names[0] Similarly: customer[1] = "Mary"; updates the second element of the array.

The indexer also performs validation to ensure that:
  • The array is not null.
  • The index is within the valid range.

If an invalid index is supplied, the get accessor returns "Unknown".

Indexers vs Properties

Property

Indexer

Has a name

Has no name

Accessed using dot operator

Accessed using square brackets

Usually exposes a single value

Usually exposes multiple values

Example: customer.Name

Example: customer[0]

Example property:

  • public string Name { get; set; }
Example indexer:
  • public string this[int index] { get; set; }

Conclusion

An indexer allows an object to be treated like an array. It is essentially a parameterized property that uses the this keyword and one or more parameters to provide indexed access to data.
Indexers are especially useful when:
  1. A class contains a collection such as an array or list.
  2. You want users of the class to access data using array-like syntax.
  3. You want to hide the internal storage details while providing a simple interface.

By using indexers, objects become easier and more intuitive to work with, especially when they manage multiple related values.

Example 4: Using an Indexer to Access Rectangular Array

Suppose a Rectange class contains a Rectangular Array. An indexer can be used to access elemenets of this Rectangular Array.

public class Rectangle
{
    private int[,] table = new int[3, 4];
    public int this[int row, int col]
    {
        get
        {
            if (row >= 0 && col >= 0)
            {
                return table[row, col];
            }
            else
            {
                return -1;
            }
        }
        set
        {
            if (row >= 0 && col >= 0)
            {
                table[row, col] = value;
            }
            else
            {
                throw new IndexOutOfRangeException("Invalid index");
            }
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        Rectangle rectangle = new Rectangle();
        // initialize table using indexer of Rectangle
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                rectangle[i, j] = i + j + 100;
            }
        }
        // print table using indexer
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                Console.Write(rectangle[i, j] + " ");
            }
            Console.WriteLine();
        }
    }
} 
OUTPUT:

No comments:

Post a Comment

Hot Topics