структура c # действует как класс, когда я этого не хочу

#c# #struct

#c# #структура

Вопрос:

Итак, я пытаюсь создать небольшую змеиную игру на C # и консоли и столкнулся с каким-то странным поведением. Я всегда думал, что структуры должны передаваться как значения, а не ссылки. Но теперь, когда я пытаюсь скопировать структуру во временный буфер, а затем нарисовать ее, по какой-то причине она присоединяется к буферу в качестве ссылки:/ Когда я изменяю drawBuffer . карта также изменяется. и я не хочу, чтобы карта была изменена.

map — это статическое значение, установленное над функцией

 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';
}
 

а карта — это структура.

 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);
                }
            }
        }
    }
    
}
 

Комментарии:

1. «скопируйте структуру во временный буфер, а затем нарисуйте ее, по какой-то причине она прикрепляется к буферу в качестве ссылки» — не могли бы вы уточнить, пожалуйста? Где вы копируете ? Что вы копируете? Куда он прикрепляется? Что означает прикрепить себя в качестве ссылки? Как вы полагаете, что есть проблема?

2. хм, я думаю, это немного неясно. прикрепление, как при изменении буфера рисования. карта также будет изменена. я хочу скопировать map в drawBuffer, чтобы я мог временно изменить drawbuffer, не затрагивая карту. @Sinatr

3. char[,,] container; является ссылочным типом. Не имеет значения, что он находится внутри a struct , копия struct означает, что оба имеют ссылки на один и тот же container массив

4. есть ли альтернатива, которая позволила бы избежать этой проблемы?

Ответ №1:

Как упоминалось UnholySheep char[,,] container , это ссылочный тип. Чтобы избежать передачи его в качестве ссылки, вы могли бы создать новую карту и передать значение напрямую следующим образом:

 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];
 

Комментарии:

1. Я решил использовать clone, если мне это снова где-нибудь понадобится, хотя я не знал, что смогу получить длину по размеру, так что это будет полезно! container = (char[,,])toClone.container.Clone();

2. Вы также можете ответить на свой вопрос тем, что вы включили в свой комментарий @jklw10, чтобы другим было легче найти решение

Ответ №2:

Вместо того, чтобы вручную копировать значения из одного места в другое, я использую встроенную функцию Clone() в конструкторе, которая принимает карту.

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

таким образом, он выглядит довольно чистым в коде.

 Map drawBuffer = new Map(map);
 

вы также можете реализовать пользовательскую функцию клонирования

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