Ответ 1
name_list2 = new List<string>(name_list1);
Это приведет к клонированию списка.
Например
List<string> name_list1 = new List<string>();
List<string> name_list2 = new List<string>();
далее в коде:
name_list1.Add("McDonald");
name_list1.Add("Harveys");
name_list1.Add("Wendys");
name_list2 = name_list1; // I make a copy of namelist1 to namelist2
Итак, с этой точки я хотел бы продолжать добавлять элемент или вносить изменения в name_list2, не затрагивая name_list1. Как это сделать?
name_list2 = new List<string>(name_list1);
Это приведет к клонированию списка.
name_list2 = new List<string>(name_list1); // Clone list into a different object
В этот момент два списка представляют собой разные объекты. Вы можете добавлять элементы в список2, не затрагивая list1
Проблема в назначении. До назначения name_list2 = name_list1;
у вас есть два разных объекта List в куче, на которые указывают переменные name_list1
и name_list2
. Вы заполняете name_list1
, что хорошо. Но назначение говорит: "сделать так, чтобы name_list2
указывал на тот же объект в куче, что и name_list1
". Список, на который name_list2
больше недоступен и будет собираться мусором. Что вы действительно хотите, это скопировать содержимое name_list1
в name_list2
. Вы можете сделать это с List.AddRange. Обратите внимание, что это приведет к "мелкой" копии, что хорошо для приведенного вами примера, где содержимое списка является строкой, но может не соответствовать желаемому, когда члены списка являются более сложными объектами. Все зависит от ваших потребностей.
Другие параметры: Глубокое клонирование
public static T DeepCopy<T>(T item)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, item);
stream.Seek(0, SeekOrigin.Begin);
T result = (T)formatter.Deserialize(stream);
stream.Close();
return result;
}
так,
вы можете использовать:
name_list2 = DeepCopy<List<string>>(name_list1);
ИЛИ
name_list2 = DeepCopy(name_list1);
также будет работать.
Вот альтернативное решение:
List<string> name_list1 = new List<string>();
List<string> name_list2 = new List<string>();
name_list1.Add("McDonald");
name_list1.Add("Harveys");
name_list1.Add("Wendys");
name_list2.AddRange(name_list1.ToArray());
Метод ToArray() копирует 'name_list1' в новый массив, который мы затем добавляем в name_list2 с помощью метода AddRange().
Мне нравится linq для этого...
Если элементы списка являются примитивами или структурами, то...
L2 = L1.ToList()
Если элементы списка являются классами, то...
L2 = L1.Select(x => x.Copy()).ToList();
Где Copy
может быть просто экспоненциальной экспозицией MemberWiseClone
, или это может быть некоторая реализация глубокой копии.
Я предпочитаю метод преобразователя Json для сериализации и десериализации, так что вам не нужно отмечать классы для сериализации, особенно у вас есть множество дочерних классов.
https://www.newtonsoft.com/json/help/html/SerializingJSON.htm
Для Примитивных Типов вы можете сделать это:
List<string> CopyList = new List<string>(OriginalList);
Для не примитивных/пользовательских типов вы можете сделать это:
List<Person> CopyList = new List<Person>();
foreach(var item in OriginalList)
{
CopyList.Add(new Person {
Name = item.Name,
Address = item.Address
});
}
Для примитивных типов:
List ClonedList = новый список (OriginalList);
Для не примитивных/пользовательских типов:
Нам необходимо выполнить глубокое копирование: глубокое копирование используется для создания полной глубокой копии внутренних ссылочных типов, для этого нам нужно настроить объект, возвращаемый MemberwiseClone().
Step1- В вашем классе наследуют от ICloneable:
открытый класс MyClass: ICloneable
Step2- Реализация метода
public MyClass Clone()
{
MyClass MyClassObj =new MyClass();
MyClassObj.Property1 = this.Property1;
.
.
MyClassObj.Property_N = this.Property_N;
return MyClass;
}
Step3- теперь клонирую ваш список
List<MyClass> MyClassClone = new List<MyClass>();
for(i=0; i<Count; i++)
{
MyClassClone.Add(OriginalClaaObj[i].Clone());
}
Это сделает глубокую копию каждого предмета объекта.
Если оба списка одного и того же сложного типа, вы можете сделать что-то вроде ниже: -
SomeClass List2 = новый список(); List1.ForEach(u => List2.Add(u));
Что я делаю, так это перебираю каждый элемент List1 и продолжаю добавлять его в List2. Я считаю, что это самый короткий способ сделать это.
Ни одно из вышеперечисленных решений не помогло мне при использовании списков объектов класса.
Это может быть использовано для копирования любого объекта в другой объект с именами общих свойств.
public static void ObjectToObject(object source, object destination)
{
// Purpose : Use reflection to set property values of objects that share the same property names.
Type s = source.GetType();
Type d = destination.GetType();
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
var objSourceProperties = s.GetProperties(flags);
var objDestinationProperties = d.GetProperties(flags);
var propertyNames = objSourceProperties
.Select(c => c.Name)
.ToList();
foreach (var properties in objDestinationProperties.Where(properties => propertyNames.Contains(properties.Name)))
{
try
{
PropertyInfo piSource = source.GetType().GetProperty(properties.Name);
properties.SetValue(destination, piSource.GetValue(source, null), null);
}
catch (Exception ex)
{
throw;
}
}
}
public static List<T> CopyList<T>(this List<T> lst)
{
List<T> lstCopy = new List<T>();
foreach (var item in lst)
{
var instanceOfT = Activator.CreateInstance<T>();
ObjectToObject(item, instanceOfT);
lstCopy.Add(instanceOfT);
}
return lstCopy;
}
Для списков используйте это: list2 = list1.CopyList();