Дублировать объект и работать с Duplicate без изменения оригинала
Предполагая, что у меня есть объект ItemVO, в котором существует уже набор свойств.
например:
ItemVO originalItemVO = new ItemVO();
originalItemVO.ItemId = 1;
originalItemVO.ItemCategory = "ORIGINAL";
Я хотел бы создать еще один дубликат, используя:
duplicateItemVO = originalItemVO;
а затем используйте duplicateItemVO и измените его свойства, БЕЗ изменения оригиналаItemVO:
// This also change the originalItemVO.ItemCategory which I do not want.
duplicateItemVO.ItemCategory = "DUPLICATE"
Как я могу достичь этого, не меняя класс ItemVO?
Спасибо
public class ItemVO
{
public ItemVO()
{
ItemId = "";
ItemCategory = "";
}
public string ItemId { get; set; }
public string ItemCategory { get; set; }
}
Ответы
Ответ 1
Вам нужно будет создать новый экземпляр вашего класса, а не просто назначить переменную:
duplicateItemVO = new ItemVO
{
ItemId = originalItemVO.ItemId,
ItemCategory = originalItemVO.ItemCategory
};
Когда вы имеете дело со ссылочными типами (любым классом), просто назначая переменную, создается копия ссылки на исходный объект. Таким образом, установка значений свойств внутри этого объекта также изменит оригинал. Чтобы предотвратить это, вам нужно фактически создать экземпляр нового объекта.
Ответ 2
Вы не можете практически копировать объект, поскольку они, скорее всего, будут иметь ссылочные типы.
Идеальный метод заключается в сериализации объекта в новый. Если вы сериализуете класс (предоставляя атрибут [Serializable] в объявлении класса).
private static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
Теперь вы можете использовать этот код:
[Serializable]
public class MyClass
{
public int a {get; set;}
public int b {get; set;}
}
var obj = new MyClass{
a = 10,
b = 20,
};
var newobj = Clone<MyClass>(obj);
Вы получите совершенно новую копию obj.
Примечание. Любой другой класс внутри MyClass также должен быть объявлен с атрибутом [Serializable].
Ответ 3
Чтобы изменить один экземпляр без изменения другого, вам нужно клонировать фактические значения этого экземпляра, а не ссылку.
Модель, используемая в .Net, предназначена для реализации ICloneable.
Таким образом, ваш код будет выглядеть так:
public class ItemVO: ICloneable
{
public ItemVO()
{
ItemId = "";
ItemCategory = "";
}
public string ItemId { get; set; }
public string ItemCategory { get; set; }
public object Clone()
{
return new ItemVO
{
ItemId = this.ItemId,
ItemCategory = this.ItemCategory
};
}
}
Теперь обратите внимание, что для использования Clone() (или вы можете сделать свой собственный, который возвращает ItemVO) вам потребуется явный прилив.
duplicateItemVO = (ItemVO) originalItemVO.Clone();
Ответ 4
класс тип ссылки, и когда вы меняете один экземпляр, он изменит арифметическое повторение. поэтому используйте тип значения для преодоления вашей задачи (например: use struct вместо класса)
public struct ItemVO { *** }
или вы можете реализовать ICloneable Interface для своего класса
Ответ 5
По умолчанию объекты являются ссылочными.
Назначить одному объекту другому объекту означает, что вы просто ссылаетесь на адрес объекта. Все изменения в любом объекте будут отображаться в обоих.
Чтобы решить эту проблему, вы должны инициализировать объект с помощью "нового" ключевого слова, а затем добавить это значение объекта в первый объект.
Ответ 6
Начиная с С# 4.5, объект базового класса содержит метод MemberwiseClone, который позволяет выполнять мелкую копию этого объекта и возвращает результат как новый экземпляр. (Если поле является типом значения, выполняется побитовая копия поля. Если поле является ссылочным типом, ссылка копируется, но упомянутый объект не является, поэтому исходный объект и его клон ссылаются к тому же объекту.)
Это полезно, если вы хотите внедрить шаблон проектирования прототипа.
Если вы хотите внедрить глубокую копию (все внутри класса дублируется как новые экземпляры), то сериализация или отражение, вероятно, являются лучшими инструментами
Ответ 7
Я предлагаю использовать как есть в ссылке ниже.
Для меня это сработало очень хорошо.
https://msdn.microsoft.com/en-us/library/system.object.memberwiseclone(v=vs.110).aspx
public Person ShallowCopy ()
{
return (Person) this.MemberwiseClone ();
}