mc_dev
mc_dev

Reputation: 281

How 'indexer' is working in this example?

This is the main class

 class Program
{
    static void Main(string[] args)
    {
        MyArray fruit = new MyArray(-2, 1);
        fruit[-2] = "Apple";
        fruit[-1] = "Orange";
        fruit[0] = "Banana";
        fruit[1] = "Blackcurrant";
        Console.WriteLine(fruit[-1]);       // Outputs "Orange"
        Console.WriteLine(fruit[0]);        // Outputs "Banana"
        Console.WriteLine(fruit[-1,0]);     // Output "O"
        Console.ReadLine();
    }
}

and here is the class for the indexer:

class MyArray
{
    int _lowerBound;
    int _upperBound;
    string[] _items;

    public MyArray(int lowerBound, int upperBound)
    {
        _lowerBound = lowerBound;
        _upperBound = upperBound;
        _items = new string[1 + upperBound - lowerBound];
    }

    public string this[int index]
    {
        get { return _items[index - _lowerBound]; }
        set { _items[index - _lowerBound] = value; }

    }

    public string this[int word, int position]
    {
        get { return _items[word - _lowerBound].Substring(position, 1); }
    }
}

So, multiDimensional indexer in defined in the 'Class MyArray'

I am not able to understand how this is working when we pass '-1' as the value of 'word' to the indexer. The value for '_lowerbound' is '-2'. So it means, the value for the return should be _items[-1 - (-2)], which makes it _items[1].

But actually it is pointing to -1 index of fruits i.e. Orange.

Please clear my doubt.

Upvotes: 2

Views: 379

Answers (4)

Paolo Moretti
Paolo Moretti

Reputation: 55956

This is you private array _items:

   0     1     2     3
┌────┐┌────┐┌────┐┌────┐
│ Ap ││ Or ││ Ba ││ Bl │          
└────┘└────┘└────┘└────┘  

This is how it appears using the indexer:

  -2    -1     0     1
┌────┐┌────┐┌────┐┌────┐
│ Ap ││ Or ││ Ba ││ Bl │          
└────┘└────┘└────┘└────┘  

The value for _lowerbound is -2.

So it means, the value for the return should be _items[-1 - (-2)], which makes it _items[1].

That's correct.

But actually it is pointing to -1 index of fruits i.e. Orange.

That's wrong. It is pointing to _items[1], i.e. Orange.

Indexers are a simple way to permit a class to be used like an array. Internally, you can manage the values presented in any fashion you wish.

_items is a zero-based array with the same length as the created MyArray object.

The indexer is just interpreting the index number supplied and map it against this underlying array.

Upvotes: 4

Adam Houldsworth
Adam Houldsworth

Reputation: 64487

This isn't a multi-dimensional array in the expected sense, it just looks like one.

Updated Answer:

It looks like you expect: fruits[-1, 0] to point to the same element as fruits[1] = "Blackcurrent". Unfortunately this isn't the case as in both instances you are actually using custom indexers, both of which modify your provided index values.

The custom indexers on MyArray are mutating the index values you are supplying before they get to the underlying string[]. This is where the confusion has come in, you are not taking into account the code in the custom indexers:

public string this[int index]
{
    get { return _items[index - _lowerBound]; }
    set { _items[index - _lowerBound] = value; }

}

public string this[int word, int position]
{
    get { return _items[word - _lowerBound].Substring(position, 1); }
}


Old Answer:

Don't confuse array index in primitive arrays with indexing on custom implementations. You can do whatever you like with the latter, it is basically just syntactic sugar over method calls. You have an indexer that takes an int, that means any valid int is a valid argument for the indexer (though maybe not for the underlying primitive array string[]).

Your index implementation subtracts lowerBound from both the get and the set, so the same index supplied at the set will result in the same element as the index supplied for the get.

The second indexer taking two parameters is doing the same index modification so will result in the same element (Orange)...

Where is the confusion? Are you expecting the second parameter of...

public string this[int word, int position]

...to somehow affect what element is returned? It is used in the Substring call of the element returned by the ordinal word - lowerBound, it does not affect what element is chosen.

Upvotes: 2

lesderid
lesderid

Reputation: 3430

Arrays in .Net languages, like C#, can't have items with negative indexes.

To circumvent this, this array class moves the item with the lowest index (index of _lowerBound) to 0. So when you access the internal array, you'll have to substract _lowerBound from the index, so it will never try to pass a negative index.

This is why -1 will actually be at 1 in the internal array, because -1 - (-2) equals to 1.

Edit: I'm not sure why you think there should be a difference between your class' two indexers. They both use _items[index - _lowerBound] to access the underlying .Net array. Other than the String.Substring call, there's no difference between the two indexers.

Try changing the code of the second indexer so it calls the first indexer, you'll see it returns the same character. (http://ideone.com/sFmDo)

Upvotes: 1

Maarten
Maarten

Reputation: 22945

The index calculated in this[int] and this[int,int] is the index as you need it in the _items array, and this array starts at index 0. So the second item there is indeed index=1, which is Orange.

Update: _items[-1] doesn't exist, this array starts at index 0.

Upvotes: 1

Related Questions