The utility is to provide a syntax for accessing, through the index, items of an object that represents a collection.
Let's say you create a class that specializes in keeping a collection of cars and you want to get a car through its index in the collection.
If indexers were not available, you would publish in your class a function, for example getItem , and to get an item the consumer would have to do something like this:
Carro carro = carros.getItem(1);
Using indexers, you can write the getItem code in the format of an indexer, and then the consumer can get an item like this:
Carro carro = carros[1];
If your class represents a collection similar to what is done by an array , it is only natural that you want to access the items the same way you do when you use an array - this is the function of indexers in C #.
Thus, indexers are just an option to offer a certain syntax to consumers in your class that represent a collection. If there were no indexers you could do it another way (publish a getItem function, for example).
This feature was widely used before the .Net Framework provided generics collections. At that time we had to create a new class every time we wanted a specialized collection on a particular type and using indexers allowed us to offer the same syntax offered by the native framework collections.
As for performance, it makes no difference whether to use indexers.