2015-12-07 3 views
0

EDIT: Тот, кто поставил вопрос как дубликат. Этот вопрос заключается в том, как создать глубокую копию. Мой вопрос заключался в том, чтобы удостовериться, что конструктор копирования вызывается при копировании списка элементов класса.Глубокая копия списка с элементами класса

Я пытаюсь сделать глубокую копию списка, который содержит пользовательские элементы класса. Если у меня есть список строк, я могу просто использовать

List<string> secondList = new List<string>(firstList); 

, а затем свободно изменять элементы второго списка без effeting те, в списке firwst. Но когда я пытаюсь сделать то же самое с пользовательским типом класса, оба списка меняются. Чтобы попытаться решить эту проблему, я сделал небольшую тестовую программу, которая просто имеет этот класс.

class TestClass 
{ 
    public string name; 

    public TestClass(string n) 
    { 
     name = n; 
    } 

    public TestClass(TestClass original) 
    { 
     name = original.name; 
    } 
} 

И вся моя программа делает это

TestClass t = new TestClass("Name1"); 
List<TestClass> list1 = new List<TestClass>(); 
list1.Add(t); 

List<TestClass> list2 = new List<TestClass>(list1); 
list2[0].name = "Name2"; 

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

+6

Try: 'песни2 = list1.Select (х => новый TestClass (х)) ToList() ' –

+2

Возможный дубликат [Объекты глубокого клонирования] (http://stackoverflow.com/questions/78536/deep-cloning-objects) – Ben

ответ

2

Проблема в том, что ваши объекты являются ссылочными типами, а списки содержат ссылки на эти объекты.

Это означает, что даже если ваш второй список имеет COPY ссылок из первого списка, ссылки по-прежнему указывают на исходные объекты.

Чтобы решить эту проблему, вы должны клонировать не ссылки в списках, а вместо фактических объектов, которые вы сохранили в списках.

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

var list2 = list1.Select(item => new TestClass(item)).ToList(); 
1

Вы создаете ссылку с этой строки кода:

List<TestClass> list2 = new List<TestClass>(list1); 

Но вы не хотите использовать Call-by-Reference. В этом подходе вам необходимо позвонить по значению .

поэтому рабочий код в лямбда-выражения заключается в следующем:

 TestClass t = new TestClass("Name1"); 
     List<TestClass> list1 = new List<TestClass>(); 
     list1.Add(t); 

     List<TestClass> list2 = new List<TestClass>(); 
     list2 = list1.Select(item => new TestClass(item)).ToList(); 
     list2[0].name = "Name2"; 

Весело с ним ...

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