Jaycee
Jaycee

Reputation: 3118

How to implement Array indexer in 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.

Upvotes: 5

Views: 931

Answers (3)

millimoose
millimoose

Reputation: 39950

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().)

Upvotes: 6

D Stanley
D Stanley

Reputation: 152491

use the this[] operator:

public int this[int i, int j]
{
    get {return 1;}
    set { ; }
}

Note that you can't have a variable number of dimensions in one operator - you have to code each method separately:

public int this[int i, int j, int k]
{
    get {return 1;}
    set { ; }
}
public int this[int i, int j]
{
    get {return 1;}
    set { ; }
}
public int this[int i]
{
    get {return 1;}
    set { ; }
}

I expect I could keep going adding dimensions to Int.MaxValue

You'd be wrong:

An array can have a maximum of 32 dimensions.

Upvotes: 1

SLaks
SLaks

Reputation: 887195

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.

Upvotes: 7

Related Questions