Eli
Eli

Reputation: 85

Use a struct as a multidimensional array index

I have a 3D array that I'm accessing this way Array(int x, int y, int z). What I would like to know, if it is possible to have a struct, that has xyz in it, so that I can use it this way: Array(struct xyz). If it is, then how?

The reason for why I would want this, is that it would be easier for me to read and write, and that it would be alot simpler and less error prone to write. Makes it easier to maintain the bigger picture.

I do know that I could make a class that has its own method, but since I have many classes and applying it to each one would make me quickly loose the readability, using the struct directly would be a better option if available.

Example:

public struct xyz
{
    public int x, y, z;

    public xyz(int X, int Y, int Z)
    {
        x = X;
        y = Y;
        z = Z;
    }
}

private void Test()
{
    int(,,) Array = new int()
    {
        {
            {0,0},
            {0,0},
        },
        {
            {0,0},
            {0,0},
        }
    };
    xyz XYZ = new xyz(0,0,0);
    Array[XYZ] = 1; // this instead of
    Array[XYZ.x, XYZ.y, XYZ.z] = 1 // this
}

Upvotes: 0

Views: 1757

Answers (3)

Windgate
Windgate

Reputation: 428

Completing the solution of @Andrew Cooper, if you also want to access that matrix normally you must add this methods (Look at the end of Andrew's code)

class MyArray<T>
{
    private T[,,] array;

    // Constructor
    public MyArray(int xSize, int ySize, int zSize)
    {
        array = new T[xSize,ySize,zSize];
    }

    // Index with your own struct XYZ
    public T this[XYZ xyz]
    {
        get { return array[xyz.x, xyz.y, xyz.z]; }
        set { array[xyz.x, xyz.y, xyz.z] = value; }
    }

    // Normal index
    public T this[int x, int y , int z]
    {
        get { return array[x, y, z]; }
        set { array[x, y, z] = value; }
    }

    // Get dimensions
    public int GetLength(int dim)
    {
        return array.GetLength(dim);
    }
}

Upvotes: 0

svick
svick

Reputation: 245008

You can easily achieve that by creating your own collection that can be accessed either by specifying all thee coordinates separately:

public T this[int x, int y, int z] { get { … } set { … } }

Or by your XYZ struct:

public T this[XYZ xyz]  { get { … } set { … } }

You can't add that indexer to array, extension indexers are not possible. What you could do is to create two extension methods. Something like:

public static T Get<T>(this T[,,] array, XYZ xyz)
{
    return array[xyz.X, xyz.Y, xyz.Z];
}

public static void Set<T>(this T[,,] array, XYZ xyz, T value)
{
    array[xyz.X, xyz.Y, xyz.Z] = value;
}

And then use it like this:

int i = array.Get(xyz);
array.Set(xyz, 25);

Also, creating mutable structs, like you did, is considered worst practice in C#. They can be very confusing.

Upvotes: 1

Andrew Cooper
Andrew Cooper

Reputation: 32596

You could create your own array class that wraps a real array, and provides an indexer to do what you want:

class MyArray<T>
{
    private T[,,] array;

    public MyArray(int xSize, int ySize, int zSize)
    {
        array = new T[xSize,ySize,zSize];
    }

    public T this[XYZ xyz]
    {
        get { return array[xyz.x, xyz.y, xyz.z]; }
        set { array[xyz.x, xyz.y, xyz.z] = value; }
    }
}

Upvotes: 1

Related Questions