Создание мелкой копии структур в C#

Я попытался найти свой ответ и нашел их в отношении C, а не C#, поэтому решил опубликовать его.

Мой вопрос может быть тривиальным здесь.

Согласно моему пониманию (простыми словами)

После завершения копирования

Shallow Copy -> основной и скопированный объект (ссылка или тип значения) должны указывать на один и тот же объект в памяти

DeepCopy -> основной и скопированный объект (ссылочный или тип значения) должен указывать на разные объекты в памяти

В дальнейшем у меня есть структура на C#, и я пытаюсь сделать ее поверхностную копию. Я пытался использовать метод "MemberwiseClone", но я думаю, что он работает только для ссылочных типов. Для типов значений я думаю, что метод MemberwiseClone поместит его в объект и распакует в другой адрес памяти в стеке.

То, что я пробовал, как показано ниже.

Мой вопрос: как (если это вообще возможно) я могу создать поверхностную копию простой структуры?

Я надеюсь, что мои основы верны здесь и не говорят ерунду. Пожалуйста, исправьте меня, если я ошибаюсь в любом из сделанных мной заявлений.

С Уважением,

Samar

struct MyStruct : ICloneable
{
    public int MyProperty { get; set; }

    public object Clone()
    {
        return this.MemberwiseClone();//boxing into object
    }
}


    private void btnChkStr_Click(object sender, EventArgs e)
    {
        MyStruct struct1 = new MyStruct();
        struct1.MyProperty = 1;

        //MyStruct struct2 = struct1; //This will create a deep copy
        MyStruct struct2 = (MyStruct)(struct1.Clone());//unboxing into structure hence allocating a different memory address
        struct2.MyProperty = 2;

        MessageBox.Show(struct1.MyProperty.ToString()); //still showing 1
    }

4 ответа

Решение

Ваши ожидания от того, что делает глубокая копия против мелкой, не верны. Мелкая копия копирует все типы значений и только ссылки на ссылочные типы. Глубокая копия копирует все типы значений и все ссылочные типы.

Таким образом, ваша структура уже выполняет поверхностную копию при выполнении:

MyStruct struct2 = struct1;

Этот пример кода (консольное приложение) показывает, что изменение значения объекта во второй структуре также изменяет значение объекта в первой структуре, поскольку объект был только что скопирован по ссылке:

class Program
{
    static void Main(string[] args)
    {
        Test t1 = new Test();
        t1.i = 1;
        t1.o = new Klasse();
        t1.o.i = 1;

        Test t2 = t1;
        t2.i = 2;
        t2.o.i = 2;

        Console.WriteLine(t1.i.ToString());
        Console.WriteLine(t1.o.i.ToString());
        Console.WriteLine(t2.i.ToString());
        Console.WriteLine(t2.o.i.ToString());
        Console.Read();
    }
}

struct Test
{
    public int i;
    public Klasse o;
}

class Klasse
{
    public int i = 0;
}

Не уверен, что вам требуется от вашей "копии". Как уже упоминалось, структуры уже копируются по значению при назначении или передаче в метод. Так может тебе ничего лишнего не нужно?

Может быть, это просто то, что вы хотите (не уверен, полезно ли это для чего-либо!):

struct MyStruct : ICloneable
{
    public int MyProperty { get; set; }

    public MyStruct Clone()
    {
        return this;
    }
    object ICloneable.Clone()
    {
        return Clone();
    }
}

Слово предупреждения: Ваш MyStruct это так называемая изменяемая структура, потому что set Право доступа к авто-собственности является публичным. Многие люди считают изменяемые структуры "злыми", потому что сочетание семантики типа значения и изменчивости может привести к неожиданному поведению.

РЕДАКТИРОВАТЬ: Если вы хотите семантику копирования по ссылке, почему вы используете struct во-первых, а не class? Структура не является ссылкой на местоположение объекта, как класс. Как и другие примеры, бокс MyStruct в object переменная сделает это object быть ссылкой на ящик, содержащий MyStruct значение. Ссылка на поле может быть скопирована по ссылке.

Вы можете создать класс, который содержит только одно поле типа экземпляра MyStruct, Тогда этот класс будет "оборачивать" вашу структуру в ссылочный тип, и вы можете копировать экземпляры такого класса с помощью обычной семантики ссылочного типа (скопируйте ссылку, сам объект не копируется).

Ваше определение мелкой копии может быть достигнуто путем явной упаковки структуры. Однако, поскольку структура упакована, получить доступ к ее свойствам нелегко!

void Main()
{
    object o1 = new M { A = 1 };
    object o2 = o1;

    // o2.A = 100 (this can also be done using dynamic)
    var prop = typeof(M).GetProperty("A");
    prop.SetValue(o2, 100);

    // prints 100, since both point to the same instance
    Console.WriteLine(((M)o1).A);
}

public struct M {
    public int A { get; set; }
}

В общем случае, хотя назначение структуры новой переменной (или вызов MemberwiseClone()) копирует все поля структуры.

Также стоит отметить, что ваши определения глубокой и мелкой копии отличаются от того, что обычно используется. В общем:

Мелкая копия: создается новый экземпляр объекта, поэтому все его члены копируются по ссылке (например, egaX и shallowCopyOfA.X по-прежнему ссылаются на один и тот же объект). Члены, которые являются типами значений (например, структуры и примитивы), копируются по значению.

Глубокая копия: создается новый экземпляр объекта, и все элементы также копируются.

Невозможно сделать такую ​​поверхностную копию структуры.

Попробуйте вместо этого использовать классы.

Другие вопросы по тегам