Indexers, Overload Indexers, Generic Indexer in C#
Definition:
An indexer allows an instance of a class can be used as an array. You can then use the instance of the class using [ ].
Syntax:
[access_specifier]
[return_type] this[parameter_list]
{
get
{
// get code here
}
set
{
// set code here
}
}
Syntex Explanation:
access_specifier: It can be public, private, protected or internal.
return_type: It can be any valid C# data type.
this: It specify the object of the current class.
parameter_list: It specifies the parameter list.
get: It is used to get values.
set: It is used to set values.
Example:
// C# program to define Indexer
using System;
public class IndexerTest
{
private int[] marks = new int[5];
// Indexer declaration
// public - access specifier of the Indexer
// int - the return type of the Indexer
// this - instance of current class
// index - parameter list of the Indexer
public int this[int index]
{
// Used to get value
get
{
return marks[index];
}
// Used to set values
set
{
marks[index] = value;
}
}
}
class IndexerMain
{
public static void Main()
{
IndexerTest iTest = new IndexerTest();
iTest[0] = 10;
iTest[1] = 20;
Console.Write("Indexer Values:\n");
Console.WriteLine("First value = {0}", iTest[0]);
Console.WriteLine("Second value = {0}", iTest[1]);
}
}
Output:
Indexer Values:
First value = 10
Second value = 20
Another Example:
// C# program for Indexer
using System;
public class IndexerTest
{
private string[] studentName = new string[10];
private static int size = 10;
public IndexerTest()
{
for (int i = 0; i < size; i++)
studentName[i] = "N. A.";
}
// Indexer declaration
public string this[int index]
{
// Used to get value
get
{
if (index >= 0 && index < size)
{
return studentName[index];
}
else
{
return "";
}
}
// Used to set values
set
{
if (index >= 0 && index < size)
{
studentName[index] = value;
}
}
}
}
class IndexerMain
{
public static void Main()
{
IndexerTest iTest = new IndexerTest();
iTest[1] = "Rahul";
iTest[2] = "Om";
Console.Write("Student Name:\n");
Console.WriteLine("First Name = {0}", iTest[0]);
Console.WriteLine("Second Name = {0}", iTest[1]);
Console.WriteLine("Third Name = {0}", iTest[2]);
}
}
Output:
Student Name:
First Name = "N. A."
Second Name = "Rahul"
Third Name = "Om"
Overloaded Indexers
Indexers can be overloaded. Below code is used to understand Overloaded Indexers:
// C# program for Indexer
using System;
public class IndexerTest
{
private string[] studentName = new string[10];
private static int size = 10;
public IndexerTest()
{
for (int i = 0; i < size; i++)
studentName[i] = "N. A.";
}
// int type indexer
public string this[int index]
{
// Used to get value
get
{
if (index >= 0 && index < size)
{
return studentName[index];
}
else
{
return "";
}
}
// Used to set values
set
{
if (index >= 0 && index < size)
{
studentName[index] = value;
}
}
}
// string type indexer
public string this[string name]
{
get
{
foreach (string str in studentName)
{
if (str.ToLower() == name.ToLower())
return str;
}
return null;
}
}
}
class IndexerMain
{
static void Main(string[] args)
{
IndexerTest iTest = new IndexerTest();
iTest[0] = "Rahul";
iTest[1] = "Amit";
iTest[2] = "Om";
Console.Write("Student Name(With int indexer):\n");
Console.WriteLine("First Name = {0}", iTest[0]);
Console.WriteLine("Second Name = {0}", iTest[1]);
Console.WriteLine("Third Name = {0}", iTest[2]);
Console.Write("Student Name(With string indexer):\n");
Console.WriteLine("First Name = {0}", iTest["Rahul"]);
Console.WriteLine("Second Name = {0}", iTest["Amit"]);
Console.WriteLine("Third Name = {0}", iTest["Om"]);
}
}
Output:
Student Name(With int indexer):
First Name = "Rahul"
Second Name = "Amit"
Third Name = "Om"
Student Name(With string indexer):
First Name = "Rahul"
Second Name = "Amit"
Third Name = "Om"
Generic Indexers
Indexer can be generic. Below code is used to understand Generic Indexers:
// C# program for Indexer
using System;
public class GenericData<T>
{
private T[] data;
public GenericData()
{
data = new T[10];
}
public GenericData(int len)
{
data = new T[len];
}
public T this[int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class IndexerMain
{
public static void Main()
{
GenericData<int> idata = new GenericData<int>();
idata[0] = 10;
idata[1] = 20;
Console.Write("Indexers with int data:\n");
Console.WriteLine("First Value = {0}", idata[0]);
Console.WriteLine("Second Value = {0}", idata[1]);
GenericData<string> sdata = new GenericData<string>();
sdata[0] = "Rahul";
sdata[1] = "Om";
Console.Write("Indexers with string data:\n");
Console.WriteLine("First Value = {0}", sdata[0]);
Console.WriteLine("Second Value = {0}", sdata[1]);
}
}
Output:
Indexers with int data:
First Value = 10
Second Value = 20
Indexers with string data:
First Value = "Rahul"
Second Value = "Om"
Indexers in Interface
Indexers can also be declared in Interfaces. Below code is used to understand Indexers in Interfaces:
// C# program for Indexer
using System;
interface IIndexer
{
string this[int index] { get; set; }
}
public class IndexerTest : IIndexer
{
private string[] studentName = new string[10];
private static int size = 10;
public IndexerTest()
{
for (int i = 0; i < size; i++)
studentName[i] = "N. A.";
}
// Indexer declaration
public string this[int index]
{
// Used to get value
get
{
if (index >= 0 && index < size)
{
return studentName[index];
}
else
{
return "";
}
}
// Used to set values
set
{
if (index >= 0 && index < size)
{
studentName[index] = value;
}
}
}
}
class IndexerMain
{
public static void Main()
{
IndexerTest iTest = new IndexerTest();
iTest[1] = "Rahul";
iTest[2] = "Om";
Console.Write("Student Name:\n");
Console.WriteLine("First Name = {0}", iTest[0]);
Console.WriteLine("Second Name = {0}", iTest[1]);
Console.WriteLine("Third Name = {0}", iTest[2]);
}
}
Output:
Student Name:
First Name = "N. A."
Second Name = "Rahul"
Third Name = "Om"
Indexers in Abstract Class
Indexers can also be declared in Abstract Classes. Below code is used to understand Indexers in Abstract Classes:
// C# program for Indexer
using System;
public abstract class AbstractIndexer
{
public abstract string this[int index] { get; set; }
}
public class IndexerTest : AbstractIndexer
{
private string[] studentName = new string[10];
private static int size = 10;
public IndexerTest()
{
for (int i = 0; i < size; i++)
studentName[i] = "N. A.";
}
// Indexer declaration
public override string this[int index]
{
// Used to get value
get
{
if (index >= 0 && index < size)
{
return studentName[index];
}
else
{
return "";
}
}
// Used to set values
set
{
if (index >= 0 && index < size)
{
studentName[index] = value;
}
}
}
}
class IndexerMain
{
public static void Main()
{
IndexerTest iTest = new IndexerTest();
iTest[1] = "Rahul";
iTest[2] = "Om";
Console.Write("Student Name:\n");
Console.WriteLine("First Name = {0}", iTest[0]);
Console.WriteLine("Second Name = {0}", iTest[1]);
Console.WriteLine("Third Name = {0}", iTest[2]);
}
}
Output:
Student Name:
First Name = "N. A."
Second Name = "Rahul"
Third Name = "Om"
Inheritance in Indexers
Inheritance is also supported by Indexers. Below code is used to understand Indexers in Interfaces:
// C# program for Indexer
using System;
public class IndexerBase
{
public string this[int index]
{
get
{
return "Base";
}
set
{
}
}
}
public class IndexerDerived : IndexerBase
{
private string[] studentName = new string[10];
private static int size = 10;
public IndexerDerived()
{
for (int i = 0; i < size; i++)
studentName[i] = "N. A.";
}
// Indexer declaration
public string this[int index]
{
// Used to get value
get
{
if (index >= 0 && index < size)
{
return studentName[index];
}
else
{
return "";
}
}
// Used to set values
set
{
if (index >= 0 && index < size)
{
studentName[index] = value;
}
}
}
}
class IndexerMain
{
public static void Main()
{
IndexerBase iBase = new IndexerDerived();
iBase[1] = "Rahul";
iBase[2] = "Om";
Console.Write("Student Name:\n");
Console.WriteLine("First Name = {0}", iBase[0]);
Console.WriteLine("Second Name = {0}", iBase[1]);
Console.WriteLine("Third Name = {0}", iBase[2]);
}
}
Output:
Student Name:
First Name = "N. A."
Second Name = "Rahul"
Third Name = "Om"
Polymorphism in Indexers
Run time polymorphism are also supported by Indexers. Below code is used to understand Indexers in Interfaces:
// C# program for Indexer
using System;
public class IndexerBase
{
public virtual string this[int index]
{
get
{
return "Base";
}
set
{
}
}
}
public class IndexerDerived : IndexerBase
{
private string[] studentName = new string[10];
private static int size = 10;
public IndexerDerived()
{
for (int i = 0; i < size; i++)
studentName[i] = "N. A.";
}
// Indexer declaration
public override string this[int index]
{
// Used to get value
get
{
if (index >= 0 && index < size)
{
return studentName[index];
}
else
{
return "";
}
}
// Used to set values
set
{
if (index >= 0 && index < size)
{
studentName[index] = value;
}
}
}
}
class IndexerMain
{
public static void Main()
{
IndexerBase iBase = new IndexerDerived();
iBase[1] = "Rahul";
iBase[2] = "Om";
Console.Write("Student Name:\n");
Console.WriteLine("First Name = {0}", iBase[0]);
Console.WriteLine("Second Name = {0}", iBase[1]);
Console.WriteLine("Third Name = {0}", iBase[2]);
}
}
Output:
Student Name:
First Name = "N. A."
Second Name = "Rahul"
Third Name = "Om"
Points to Remember
- Indexers require this keyword to create.
- If a property contains a parameter, it is called an indexer.
- Indexers are implemented using [] inside get and set.
- Indexers have not contained ref and out parameter.
- Indexers are identified by their parameter list.
- Indexers can be overloaded.
- Indexers are class instance, so can't be static.
Difference between Indexers and Properties
Indexers | Properties |
Indexers require this keyword to create. | Properties don't require this keyword. |
Indexers are identified by their parameter list. | Properties are identified by their name. |
Indexers can be overloaded. | Properties can't be overloaded. |
Indexers are accessed using array indexes. | Properties are accessed using their name. |
Indexers are class instance, so can't be static. | Properties can be static. |
Parameter can be passed in Indexers. | Parameter can't be passed in Properties. |