Indexers in C#
The term index brings to mind arrays or collections; we can get or set a value of the array by giving the index. If we want a class or struct to have this ability, we would use Indexers. Let’s continue with concrete examples.
Think that you have a class that contains an array but you don’t want consumer code to access it directly… In this condition, indexer is the right choice!
class SampleData
{
private string[] SampleArray = new string[3] {
"Shirt", "Sweater", "Hat" }; public string this[int index]
{
get { return SampleArray[index]; }
set { SampleArray[index] = value; }
}
}static void Main(string[] args)
{
var instance = new SampleData();
var secondValue = instance[1];
Console.WriteLine("Second value is " + secondValue);
}// Output
// Second value is Sweater
//
As you see above, indexer is defined with this[..] keyword. The user who uses the SampleData class, do not need to know the structure that data is held into. Actual data structure can be list, array, dictionary etc. Let’s continue with some other sample usages of indexer.
Indexers can be multidimensional.
class SampleData
{
private string[,] SampleArray = new string[3,3];
public string this[int i, int j]
{
get { return SampleArray[i, j]; }
set { SampleArray[i, j] = value; }
}
}
Indexers can be overloaded.
class SampleData
{
private string[] SampleArray = new string[3] {
"Shirt", "Sweater", "Hat" }; public string this[int index]
{
get { return SampleArray[index]; }
set { SampleArray[index] = value; }
} public int? this[string name]
{
get {
for (var i = 0; i < SampleArray.Length; i++)
if (SampleArray[i] == name)
return i;
return null;
}
}
}
Indexers can be declared with generic type.
class SampleData<T>
{
private T[] SampleArray = new T[100];
public T this[int i]
{
get => SampleArray[i];
set => SampleArray[i] = value;
}
}
Where do I need indexer in real life?
Let’s think that we need to have a structure that holds tokens by key. We don’t want to expose all data to consumer so we have to encapsulate it somehow. In this case we can create a class which has indexer and just publicly open indexer access to the consumers. So only the users, who know key, are able to retrieve actual token. You can see the simple implementation in below.
class TokenData
{
//Key -> username
//Value -> token
private Dictionary<string, string> TokenDict =
new Dictionary<string, string>()
{
{ "alice.parrot", "6C8ABB6C-32A9-4199-A328-97AE7CA868D2"},
{ "john.mark", "8D8D02AC-1496-4AF7-93E5-CC6816E29EE6"},
{ "matt.henry", "952E2F91-0842-47A9-9F9B-DBEB4C742B2B"}
}; public string this[string key]
{
get => TokenDict[key];
set => TokenDict[key] = value;
}
}static void Main(string[] args)
{
var tokenData = new TokenData();
var token = tokenData["john.mark"];
Console.WriteLine("Token that belongs to 'john.mark' is " +
token);
}// Output
// Token that belongs to 'john.mark' is
// 8D8D02AC-1496-4AF7-93E5-CC6816E29EE6
//
Additional Information
- Indexers can not be passed as a ref or out parameter.
- Indexers can not be a static member.