Learn About Indexer In C#

In this article, I am going to share with you about Indexer in C#
 
What is Indexer?
  • Indexer is used for treating objects as an array.
  • Indexer is a property that allows instances of class or struct to be indexed similar to an array.
  • Indexer is also known as a smart array, or one can say indexer as Parameterized property.
  • With Indexer, class or struct instances can be accessed using [] array access operator.
  • Indexer makes the syntax-syntactic sugar. Means make code concise and easy to understand.
  • Indexer uses 'get' and 'set' accessor similar to property. 'get' accessor returns a value. 'set' accessor set a value. The 'value' keyword used to define the value being assigned by the 'set' accessor.
Syntax of Indexer is,
  1. <access_modifier> <return_type> this [<Parameters_list>]  
  2.    {  
  3.          //Implementation of get and/or set accessor  
  4.     }   
Here, access_modifier can be public, private, protected or internal  return_type can be any valid return type(int, string, bool etc) other than void Parameters_list must contain one or more than one parameter.
 
Example
  1. public int this[int x]  
  2. {  
  3.     get { return x; }  
  4.     set { value = x; }  
  5. }  
  • Indexer name must be 'this' keyword.
  • Indexer can be public, private, protected or internal.
  • Indexer can be used when a class represents a list, collection or array of objects.
Code
 
Here, in the below problem, we have created an indexer in class 'Main'. With indexer, we are putting and retrieving values to an array of int type. Indexer uses get and set accessor to get and set value from/to the array. Indexer name should be 'this'. Inside class 'Program', we have created an object of class 'Main' and that object is now working similar to an array. The reason is one and only indexer. Indexer allows the object to be treated as an array as shown in the program. Index on which value is not assigned will be by default set to 0.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4.   
  5. namespace Tutpoint  
  6. {  
  7.     class Main  
  8.     {  
  9.         // Array of int type  
  10.         public int[] int_array = new int[10];  
  11.   
  12.         // Indexer  
  13.         public int this[int x]  
  14.         {  
  15.             get  
  16.             {  
  17.                 return int_array[x];  
  18.             }  
  19.             set  
  20.             {  
  21.                 int_array[x] = value;  
  22.             }  
  23.         }  
  24.     }  
  25.   
  26.     class Program  
  27.     {  
  28.   
  29.         static void Main(string[] args)  
  30.         {  
  31.             Main main = new Main();  
  32.   
  33.             //Object treating as an array  
  34.             main[0] = 222;  
  35.             main[8] = 33;  
  36.             main[6] = 11;  
  37.             main[2] = 1;  
  38.             main[3] = 6;  
  39.             for (int i = 0; i < main.int_array.Length; i++)  
  40.             {  
  41.                 Console.WriteLine(main.int_array[i]);  
  42.             }  
  43.             Console.ReadLine();  
  44.         }  
  45.     }  
  46. }  
Output
  1. 222  
  2. 0  
  3. 1  
  4. 6  
  5. 0  
  6. 0  
  7. 11  
  8. 0  
  9. 33  
  10. 0  
Note
 
Here for this program, we have to use index between 0 to 9 according to the size of an array else runtime 'IndexOutOfRangeException' will generate as "Index was outside the bounds of the array".
 
Some of the examples,
main[-3] = 6;
main[93] = 60;
  • Indexer can be overloaded means that a class can contain more than one indexer but with different parameters.
In the below program, we have created 3 indexers with different parameters. An object created of the class 'Main' then be used with proper arguments and accordingly Indexer will be called. This is similar to method overloading.
 
Code
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4.   
  5. namespace Tutpoint  
  6. {  
  7.     class Main  
  8.     {  
  9.         public int[] int_array = new int[10];  
  10.   
  11.         // Indexer with one parameter of int type  
  12.         public int this[int x]  
  13.         {  
  14.             get  
  15.             {  
  16.                 return int_array[x];  
  17.             }  
  18.             set  
  19.             {  
  20.                 int_array[x] = value;  
  21.             }  
  22.         }  
  23.   
  24.         // Indexer with two parameters(int, string)  
  25.         public int this[int x, string str]  
  26.         {  
  27.             get  
  28.             {  
  29.                 return int_array[x];  
  30.             }  
  31.             set  
  32.             {  
  33.                 if (str != null)  
  34.                     int_array[x] = str.Length;  
  35.                 else  
  36.                     int_array[x] = value;  
  37.             }  
  38.         }  
  39.   
  40.         // Indexer with two parameters(int, bool)  
  41.         public int this[int x, bool b]  
  42.         {  
  43.             get  
  44.             {  
  45.                 return int_array[x];  
  46.   
  47.             }  
  48.             set  
  49.             {  
  50.                 if (b)  
  51.                     int_array[x] = value;  
  52.                 else  
  53.                     int_array[x] = 1;  
  54.             }  
  55.         }  
  56.   
  57.     }  
  58.   
  59.     class Program  
  60.     {  
  61.   
  62.         static void Main(string[] args)  
  63.         {  
  64.             Main main = new Main();  
  65.             main[1] = 10;  
  66.             main[2] = 20;  
  67.             main[3] = 30;  
  68.             main[4, "john"] = 40;  
  69.             main[5, "Player rock"] = 50;  
  70.             main[6, "Snow the Bastard!!"] = 60;  
  71.             main[7, true] = 70;  
  72.             main[8, false] = 80;  
  73.             main[0, true] = 0;  
  74.             main[9, false] = 90;  
  75.   
  76.             for (int i = 0; i < main.int_array.Length; i++)  
  77.             {  
  78.                 Console.WriteLine(main.int_array[i]);  
  79.             }  
  80.   
  81.             Console.ReadLine();  
  82.         }  
  83.     }  
  84. }  
Output
  1. 0  
  2. 10  
  3. 20  
  4. 30  
  5. 4  
  6. 11  
  7. 18  
  8. 70  
  9. 1  
  10. 1  
Note 
If we create 2 indexers with same parameters of the same type in the same sequence but different return type the compiler will generate an error as "Type 'Main' already defines a member called 'this' with the same parameter types".
  1. // Indexer with one parameter of int type  
  2. public int this[int x]  
  3. {  
  4.     get  
  5.     {  
  6.         return 100;  
  7.     }  
  8.     set  
  9.     {  
  10.         x = value;  
  11.     }  
  12. }  
  13.   
  14. // Indexer with same parameters of the same type in the same sequence but different return type  
  15. // Error as "Type 'Main' already defines a member called 'this' with the same parameter types"  
  16. public string this[int x]  
  17. {  
  18.     get  
  19.     {  
  20.         return "john";  
  21.     }  
  22.     set  
  23.     {  
  24.         x = Convert.ToInt32(value);  
  25.     }  
  26. }  
Can't-Do Activities

Static keyword cannot be used with indexers.
If we use 'static' keyword with indexer then the compiler will produce a compile time error as "The modifier 'static' is not valid for this item"
  1. // Compile time error as "The modifier 'static' is not valid for this item"  
  2. public static int this[int x]  
  3. {  
  4.     get { return x; }  
  5.     set { value = x; }  
  6. }  
Indexer must contain at least one parameter.
If indexer does not contain any parameter then the compiler will produce a compile time error as "Indexers must have at least one parameter"
  1. // Compile time error as "Indexers must have at least one parameter"  
  2. public int this[]  
  3. {  
  4.     get { return x; }  
  5.     set { value = x; }  
  6. }  
Indexer must have a valid return type other than void.
If we use indexer of void type then the compiler will produce a compile time error as "Indexers cannot have void type"
  1. // Compile time error as "Indexers cannot have void type"  
  2. public void this[int x]  
  3. {  
  4.     get { return x; }  
  5.     set { value = x; }  
  6. }  
'ref' and 'out' keywords cannot be used with indexers.
If we use 'ref' and 'out' keywords on indexer then the compiler will produce a compile time error as "ref and out are not valid in this context"
  1. // Compile time error as "ref and out are not valid in this context"  
  2. public string this[ref string x, int y, out int z]  
  3. {  
  4.     get  
  5.     {  
  6.         return "john";  
  7.     }  
  8.     set  
  9.     {  
  10.         x = value;  
  11.     }  
  12. }  
Name attribute is used to define Indexer with a name.
  1. [System.Runtime.CompilerServices.IndexerName("Main")]  
  2. public string this[string x]  
  3. {  
  4. }  
Difference between Indexer and Property
  1. Indexer is created with 'this' keyword while Property doesn't require 'this' keyword.
  2. Indexer is identified by signature while Property is identified with their name.
  3. Indexer is accessed using indexes while Property is accessed with their name.
  4. Indexer cannot be static while Property can be static.
  5. 'get' accessor of an indexer has parameter list while 'get' accessor of a property has no parameters.
  6. 'set' accessor of an indexer has parameter list in addition to the value parameter while 'set' accessor of a property contains value parameter only.
  7. Indexer can be overloaded while property cannot be overloaded. 
Conclusion
 
An indexer is a syntactic sugar which makes code concise and easy to understand. An indexer is good to use when we are dealing with either of them(array, list, collection etc.). I hope this article helps you to understand a bit more about Indexers.
 
Thank you. Please feel free to ask any question or make a suggestion. You can read my other articles or blogs on this link. C# Articles