jklw10
jklw10

Reputation: 117

c# struct acts like class when i don't want it to

So I'm trying to make a little snake game in C# and console and ran into some weird behavior. I've always thought structs are supposed to be passed around as values not references. But now that I try to copy a struct to a temporary buffer and then draw that, for some reason it attaches itself to the buffer as a reference :/ When I modify the drawBuffer. the map also gets modified. and i don't want the map to be modified.

map is a static value established above the function

Map drawBuffer = new Func<Map>(() => map)(); //trying to forcibly pass the value through a function as an attempt to separate it from the refrence.
MovePlayer();
foreach ((int x, int y) in player.Tail)
{
    drawBuffer[x, y, 1] = 'O';
}

and Map is a struct.

struct Map //also tried to make it immutable via readonly; nothing.
{
    public const char EMPTY = (char)0;
    public int Width;
    public int Height;
    public int Depth;
    char[,,] container;
    public char this[int x, int y, int z]
    {
        get
        {
            return container[x, y, z];
        }
        set
        {
            container[x, y, z] = value;
        }
    }
    public char this[int x, int y]
    {
        get
        {
            for (int z = Depth - 1; z >= 0; z--)
            {
                if (container[x, y, z] != EMPTY)
                {
                    return container[x, y, z];
                }
            }
            return EMPTY;
        }
    }
    public void DrawSurface()...
    public void DrawLayer(int z)...
    public Map(int width, int height, int depth)
    {
        this.Width = width;
        this.Height = height;
        this.Depth = depth;
        container = new char[width, height, depth];
    }
    public Map(int width, int height, int depth, Func<int, int, int, int, int, int, char> pattern)
    {
        this.Width = width;
        this.Height = height;
        this.Depth = depth;
        container = new char[width, height, depth];
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                for (int z = 0; z < depth; z++)
                {
                    this[x, y, z] = pattern(x, y, z, width, height, depth);
                }
            }
        }
    }
    
}

Upvotes: 0

Views: 86

Answers (2)

jklw10
jklw10

Reputation: 117

Instead of manually copying the values from one place to another, I use the built in Clone() function in a Constructor that takes in a map in.

public Map(Map toClone)
{
    Width = toClone.Width;
    Height = toClone.Height;
    Depth = toClone.Depth;
    container = (char[,,])toClone.container.Clone();
}

this way it looks pretty clean in code.

Map drawBuffer = new Map(map);

you could also implement a custom clone function

public Map Clone(Map toClone){
    Map newMap = new map(toClone.Width, toClone.Height, toClone.Depth)
    newMap.container = (char[,,])toClone.container.Clone();
    return newMap;
}

Upvotes: 1

66Gramms
66Gramms

Reputation: 743

As mentioned by UnholySheep char[,,] container is a reference type. To avoid passing it as a reference you could make a new map and pass the valuse directly like so:

Map secondMap;
for (int z = 0; z < drawBuffer.container.GetLength(2); z++)
    for (int y = 0; y < drawBuffer.container.GetLength(1); y++)
        for (int x = 0; x < drawBuffer.container.GetLength(0); x++)
            secondMap.container[x, y, z] = drawBuffer.container[x, y, z];

Upvotes: 2

Related Questions