Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement Array indexer in C#

Tags:

arrays

c#

I can type

Square[,,,] squares = new Square[3, 2, 5, 5];
squares[0, 0, 0, 1] = new Square();

In fact, I expect I could keep going adding dimensions to Int.MaxValue though I have no idea how much memory that would require.

How could I implement this variable indexing feature in my own class? I want to encapsulate a multi dimensional array of unknown dimensions and make it available as a property thus enabling indexing in this manner. Must I always know the size in which case how does Array work?

EDIT

Thanks for the comments, here is what I ended up with - I did think of params but didn't know where to go after that not knowing about GetValue.

class ArrayExt<T>
{
  public Array Array { get; set; }

  public T this[params int[] indices] 
  {
      get { return (T)Array.GetValue(indices); }
      set { Array.SetValue(value, indices);}
  }
}

ArrayExt<Square> ext = new ArrayExt<Square>();
ext.Array = new Square[4, 5, 5, 5];
ext[3, 3, 3, 3] = new Square();

TBH I don't really need this now. I was just looking for a way to extend Array to initialize its elements having resolved to avoid for loop initialization code outside the class whenever I was using a multi array (mainly in unit tests). Then I hit intellisense and saw the Initialize method...though it restricts me to a default constructor and value types. For reference types an extension method would be required. Still I learnt something and yes, there was a runtime error when I tried an array with more than 32 dimensions.

like image 793
Jaycee Avatar asked Sep 09 '13 22:09

Jaycee


2 Answers

Arrays types are magic – int[] and int[,] are two different types, with separate indexers.
These types are not defined in source code; rather, their existence and behavior are described by the spec.

You would need to create a separate type for each dimensionality – a Matrix1 class with a this[int], a Matrix2 class with a this[int, int], and so on.

like image 184
SLaks Avatar answered Oct 01 '22 10:10

SLaks


You could use varargs:

class Squares {
    public Square this[params int[] indices] {
        get {
            // ...
        }
    }
}

You'd have to handle the fact indices can have an arbitrary length yourself, in whicheevr way you feel is appropriate. (E.g. check the size of indices against the array rank, type it as Array and use GetValue().)

like image 41
millimoose Avatar answered Oct 01 '22 11:10

millimoose