0

I am trying to understand indexers in C#. In the accepted answer, I am not able to understand how:

public float this[int index]
{
    get{
        return temps[index];
    }
    set{
        temps[index] = value;
    }
}

works. As in what if I have 2 float variables?

kesarling He-Him
  • 1,944
  • 3
  • 14
  • 39
  • its just a special property. have you read the microsoft documentation? – Daniel A. White Jul 30 '20 at 03:26
  • if you have multiple float values you can return a tuple. – Daniel A. White Jul 30 '20 at 03:27
  • What does `temps` in `public float temps this[int index]` mean? – Sweeper Jul 30 '20 at 03:48
  • 1
    I saw someone's youtube video. It is very good: https://www.youtube.com/watch?v=HdtEQqu0yOY – Saiansh Singh Jul 30 '20 at 03:49
  • Can you share what exactly you want to achieve by doing `public float temps this[int index]`? And what's not understandable ? – Chetan Jul 30 '20 at 03:51
  • 1
    If you have two float arrays, you want to return two float values from both the arrays at the same index? In that case you can return `Tuple` instead of single float value.. – Chetan Jul 30 '20 at 03:57
  • 1
    If I remember correctly, in VB you can have multiple named indexers. However, in C#, you can have only an unnamed indexers (though you can override it by having multiple indexers each with a different *type* of index variable. The idea of an indexer is to allow an object to behave as if it is an indexed collection. That's how, if you have a `Dictionary` named `d`, you can write `int val = d["key"];`. DataReaders, for example, can be indexed by an int or a string – Flydog57 Jul 30 '20 at 04:06

1 Answers1

3

To put it simply, Idexers is a technique that you can use to allow a class to behave in a similar way to an array, by allowing you can access values by using an index.

  • generally you would only do this if conceptually the class is supposed to behave like an array, its primary function is to hold a single collection of other objects.

A common scenario is when the class is a wrapper for an internal array variable that you do not want to directly expose. We try to avoid classes inheriting from arrays or IEnumerable because there is a lot of functionality to implement, but wrapping an array for the purposes of adding additional functionality can make a lot of sense.

temps in your syntax public float temps this[int index] doesn't make sense, and is not necessary because a class can only have a single indexer of each type.

Instead of using an indexer, if the temps field was exposed as public, then you could use this syntax instead to access the value for the index of 5:

TempratureRecord oTest = new TemperatureRecord();
var tempAtIndex5 = oTest.temps[5];

But now you have access to the temps variable itself, meaning you could reassign it altogther.

Do not mistake that example as the only way to expose values from internal arrays, if you had multiple arrays then you can expose them in different ways, generally NOT by using an indexer.

If the indexer only exposes an internal array, but offers nothing more, then that's probably not a great reason to use them at all.

You can have an indexer of say type string and a separate indexer of type int, this is a common pattern if the internal array is an array of objects that might have both a unique string and int property that can be used to identify the correct object to return.

However you would not generally do this just because you have an array of ints and an array of strings. The general expectation of Indexers is that if there are multiple indexers, we are offering the caller a different way to access the same conceptual list of objects, and indeed to target the same object in different ways, perhaps because we do not know the index of that object in the internal array.

An example of how multiple indexers might be used to access the same internal array, but showing how the index passing in doesn't have to be the index at all that is used internally:
Note: by doing it this way, it may not make sense to allow a setter at all

public class Person
{
    string Name { get; set; }
    int Id { get; set; }
}

public class People
{
    private Person[] _backingStore; 
    
    /// <summary>Instantiate a new list of people</summary>
    public People(params Person[] persons)
    {
        _backingStore = persons;
    }

    /// <summary> Return a person from this list by Id </summary>
    public Person this[int id]
    {
        get{
            return _backingStore.Where(p => p.Id == id).FirstOrDefault();
        }
    }
    /// <summary> Return a person from this list by Name </summary>
    public Person this[string name]
    {
        get{
            return _backingStore.Where(p => p.Name == name).FirstOrDefault();
        }
    }
}

...

People list = new People(
    new Person(){ Id = 26, Name = "Hassan" },
    new Person(){ Id = 101, Name = "John Skeet" }
);  

var john = list["John Skeet"];
var alsoJohn = list[101];
var no1 = list["someone else"];
var hassan = list["Hassan"];

Chris Schaller
  • 13,704
  • 3
  • 43
  • 81