2013-08-02 2 views
1

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

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

В соответствии с моим пониманием (в простых терминах)

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

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

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

Продолжая это, у меня есть структура на C# и попытка сделать мелкую копию того же самого. Я попытался использовать метод «MemberwiseClone», но я думаю, что он работает только для ссылочных типов. Для типов значений я думаю, что метод «MemberwiseClone» помещает его в объект и распаковывает его в другой адрес памяти в стеке.

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

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

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

С уважением,

Самар

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 
    } 
+3

[структура] (http://msdn.microsoft.com/library/saxz13w4.aspx):. «Структуры копируются по заданию При struct присваивается новой переменной, все данные копируются, и любая модификация новой копии делает n или изменить данные для оригинальной копии. Это важно помнить при работе с коллекциями типов значений, таких как «Словарь <строка, myStruct>». - У вас не может быть мелкой копии структуры. – Corak

+0

Попытка иметь мелкую копию «изменчивого» текста, значение типа неправильное – doctorlove

+0

Зачем вам это нужно? – musefan

ответ

5

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

Так что ваша структура уже выполняет неполную копию при выполнении:

MyStruct struct2 = struct1; 

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

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; 
} 
+0

Итак, что вы пытаетесь сказать, что касается типов ценностей, точная копия и глубокая копия - это одно и то же? – samar

+0

Да, это правильно. –

0

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

Рассмотрите возможность использования классов.

2

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

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()), будет копировать все поля структуры.

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

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

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

+0

' Нет перегрузки для метода SetValue принимает 2 аргумента', однако вы можете использовать 'prop.SetValue (o2, 100, null) ' – musefan

+1

@musefan [Используется перегрузка] (http://msdn.microsoft.com/en-us/library/hh194291.aspx) является новой в среде .NET 4.5. Если у вас ее нет , используйте '.SetValue (o2, 100, null)', как вы говорите (.NET 4.0 a и раньше). –

1

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

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

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

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

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

EDIT: Если вы хотите скопировать по ссылке семантику, почему вы используете struct в первую очередь, а не class? Строка не является ссылкой на местоположение объекта, как класс. Как и другие примеры, бокс MyStruct в переменной object сделает это object ссылкой на поле , содержащее значение MyStruct. Ссылка на поле может быть скопирована по ссылке.

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

+0

OP хочет знать, как копировать как ссылку, а не как значение – musefan

+0

@musefan Возможно, вы правы. Я попытался добавить еще немного информации к моему ответу, но я чувствую, что мой ответ становится еще более запутанным, чем вопрос. –

Смежные вопросы