Friday, June 18, 2021

C# Indexer

C# Indexer is a special type of property of a class/structure that allows us to access different members of instances of a class or structure using class as a virtual array or dictionary. The indexer has a parameter which acts. Indexer is overloaded by change in the datatype of its parameter. C# allows us to define overloaded, custom and generic indexers. 

We can better understand indexer by examples. Let's take the following example. Suppose there is class named Employee with members like Id, Name, Salary, Designation. The Employee class is given below.
class Employee
{
    public int Id {get; set;}
    public string Name {get; set;}
    public double Salary {get; set;}
    public string Designation {get; set;}
}

Let's create an instance of the Employee using default constructor.
Employee Emp = new Employee();

Now the question is, can we refer the properties/members of the Employee class using index?
Emp[0] refers to id i.e. 1st property of Emp object
Emp[1] refers to Name i.e. 2nd property of Emp object
Emp[2] refers to Salary i.e. 3rd property of Emp object
Emp[3] refers to Designation i.e. 4th property of Emp object
Note that each index returns different data type value.
Indexer is used to achieve above type of goal.

Syntax of defining an Indexer
<access-modifier> <type> this[datatype parameter]
{
    //the indexer block with getter and setter blocks
}

Indexer has getter and setter blocks which are written inside the indexer block.
public returnType this[datatype parameter]
{
    get { return className[index] }
    set { className[index] = value}
}
Indexer is declared for a class after writing this[datatype parameter] (for example, this[int index]) after return type. Here in this[int index], index is parameter of the indexer. The parameter of indexer can be of any datatype. We should also give the access specifier before the class name. The access-modifier can be public, private, protected and internal. The this keyword implies the class inside which the indexer is defined. The this keyword refers to current class.

POINTS TO REMEMBER
  1. Indexer is defined inside a class for this current class.
  2. Indexer has access specifier which can be public, private, protected or internal.
  3. The return type of indexer is written after its access specifier.
  4. After the return type, this keyword is written which is followed by square brackets and inside this brackets parameter of the indexer is given with its data type. Thereafter, indexer block begins which is denoted by {}
  5. Indexer block {} contains getter and setter blocks.
  6. The indexer get and set blocks use the indexer parameter to return or assign value to class properties. 
Example of Employee class Indexer

using System;
namespace IndexerEx
{
    class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public double Salary { get; set; }
        public string Designation { get; set; }
        //parameterized constructor
        public Employee(int Id, string Name, double Salary, string Designation)
        {
            this.Id = Id;
            this.Name = Name;
            this.Salary = Salary;
            this.Designation = Designation;
        }
        //indexer of Employee class
        public object this[int index]
        {
            get
            {
                switch (index)
                {
                    case 0:
                        return Id;
                    case 1:
                        return Name;
                    case 2:
                        return Salary;
                    case 3:
                        return Designation;
                    default:
                        return null;
                }
            }

            set
            {
                switch (index)
                {
                    case 0:
                        Id=(int)value; //unboxing
                        break;
                    case 1:
                        Name= value.ToString();
                        break;
                    case 2:
                        Salary = (double)value; //unboxing
                        break;
                    case 3:
                        Designation = value.ToString();
                        break;
                    default:
                        break;
                }

            }
        }

    }

    class Program
    {
       //Consuming Indexer of Employee class
        static void Main(string[] args)
        {
            Employee employee = new Employee(1, "Amar",20000.0,"Accountant");
            Console.WriteLine(employee[0]);
            Console.WriteLine(employee[1]);
            Console.WriteLine(employee[2]);
            Console.WriteLine(employee[3]);
            Console.ReadKey();
        }
    }
}
OUTPUT
1
Amar
20000
Accountant
Question: What will be the benefit if we could refer the members of the class using indices, i.e. indexer?
Answer: The initialization of the fields of the class will become easier. Particularly in case of get and set blocks of the property of class, we can use indexer of the class to facilitate the initialization of the fields of the class.

The parameter of indexer of a class can be of any type. For the above, Employee class, now we use string data type parameter for its indexer. This will be case of Indexer Overloading.

using System;
namespace IndexerEx
{
    class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public double Salary { get; set; }
        public string Designation { get; set; }
        //parameterized constructor
        public Employee(int Id, string Name, double Salary, string Designation)
        {
            this.Id = Id;
            this.Name = Name;
            this.Salary = Salary;
            this.Designation = Designation;
        }
        //indexer of Employee class
        public object this[string empProperty]
        {
            get
            {
                switch (empProperty)
                {
                    case "Id":
                        return Id;
                    case "Name":
                        return Name;
                    case "Salary":
                        return Salary;
                    case "Designation":
                        return Designation;
                    default:
                        return null;
                }
            }

            set
            {
                switch (empProperty)
                {
                    case "Id":
                        Id =(int)value;
                        break;
                    case "Name":
                        Name = value.ToString();
                        break;
                    case "Salary":
                        Salary = (double)value;
                        break;
                    case "Designation":
                        Designation = value.ToString();
                        break;
                    default:
                        break;
                }

            }
        }

    }

    class Program
    {
       //Consuming Indexer of Employee class
        static void Main(string[] args)
        {
            Employee employee = new Employee(1, "Amar",20000.0,"Accountant");
            Console.WriteLine(employee["Id"]);
            Console.WriteLine(employee["Name"]);
            Console.WriteLine(employee["Salary"]);
            Console.WriteLine(employee["Designation"]);
            Console.ReadKey();
        }
    }
}

OUTPUT
1
Amar
20000
Accountant

MAIN POINTS  REPEATED
  1. Indexer is defined inside a class for this current class.
  2. Indexer has access specifier which can be public, private, protected or internal.
  3. The return type of indexer is written after its access specifier.
  4. After the return type, this keyword is written which is followed by square brackets and inside this brackets parameter of the indexer is given with its data type. Thereafter, indexer block begins which is denoted by {}
  5. Indexer block {} contains getter and setter blocks.
  6. The indexer get and set blocks use the indexer parameter to return or assign value to class properties. 
  7. Indexer can be overloaded inside the class in which it is defined.
  8. Generic indexer is also possible.
  9. Indexer has only one parameter.
  10. Indexer parameter can be numeric or string data type.
  11. Indexer cannot be static.

No comments:

Post a Comment

Hot Topics