Author : MD TAREQ HASSAN | Updated : 2021/03/22
What is Indexer
- Properties can be static but indexers cannot be
- Does not support shortened syntax as like auto prop
- Indexers can also be declared with multiple parameters and each parameter may be a different type
- Indexers do not have to be indexed by an integer value; it is up to you how to define the specific look-up mechanism.
- Indexers can be overloaded
- The signature of an indexer consists of the number and types of its formal parameters. It doesn’t 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, you cannot pass an indexer value as a ref or out parameter.
Why to use indexers?
- Instead of a new data structure, class itself is a data structure
- Simplified Syntax -> syntactic sugar
var tr = new Temp();
var firstTemp = tr[0] // instead of: var firstTemp = foo.tempArray[0]
Indexer systax
// Indexer is highly specialized property which allows instances of a class (or struct to) be indexed just like arrays
public int this[int index] // Indexer declaration
{
// get and set accessors
}
// generic implementation
public class Person<T> {
//backing store array
private T[] arr = new T[100];
public T this[int i] {
get{ return arr[i]; }
set {
arr[i] = value;
}
}
}
Usage of Indexer
Usage 1: if your class represents list(/array) of its instances => use indexer
public Class Person {
public string Name{get; set;}
private Person[] _backingStore;
public Person this[int index] {
get{ return _backingStore[index]; }
set{
_backingStore[index] = value;
}
}
}
Person person = new Person();
person[0] = new Person() { Name = "Hassan" };
person[1] = new Person() { Name = "John Skeet" };
Usage 2: if your class represents list(/array) of values directly related to your class => use indexer
class TempratureRecord{
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
public int Length {
get { return temps.Length; }
}
public float this[int index] {
get{ return temps[index]; }
set{
temps[index] = value;
}
}
}
Indexer in interface
public interface ISomeInterface{
// Indexer declaration:
string this[int index]{ get; set; }
}
Expression Body Definitions
class SampleCollection<T> {
private T[] arr = new T[100];
int nextIndex = 0;
public T this[int i] => arr[i];
public void Add(T value){
if (nextIndex >= arr.Length) {
throw new IndexOutOfRangeException($"The collection can hold only {arr.Length} elements.");
}
arr[nextIndex++] = value;
}
}
var stringCollection = new SampleCollection<string>();
stringCollection.Add("Hello, World");
System.Console.WriteLine(stringCollection[0]);
// both the get and set accessor can be an implemented as expression-bodied members
class SampleCollection<T>
{
// Declare an array to store the data elements.
private T[] arr = new T[100];
// Define the indexer to allow client code to use [] notation.
public T this[int i]
{
get => arr[i];
set => arr[i] = value;
}
}