Как клонировать объекты

Когда я делаю следующее: все, что делается для Лица b, изменяет Person a (я думал, что это будет клонировать Person b от Person a). У меня также нет идеи, если смена Person a изменит Person b после ссылки. Из-за моего кода прямо сейчас, я могу видеть это только в одном направлении.

Person a = new Person() { head = "big", feet = "small" }; Person b = a; b.head = "small"; //now a.head = "small" too 

Теперь, если я сделаю это вместо этого. Человек a станет полностью отдельным.

 Person b = new Person() { head = a.head, feet = a.feet }; 

Теперь это прекрасно и любопытно имеет смысл при сравнении этого поведения с другими вещами на C #. НО, это может сильно раздражать большие объекты.

Есть ли способ сократить это?

Такие как:

Person b = a.Values;

Есть ли способ сократить это?

Нет, не совсем. Вам нужно будет создать новый экземпляр, чтобы исходный текст не влиял на «копию». Для этого есть несколько вариантов:

  1. Если ваш тип является struct , а не class , он будет скопирован по значению (вместо простого копирования ссылки на экземпляр). Это даст вам семантику, которую вы описываете, но имеет много других побочных эффектов, которые, как правило, менее желательны, и не рекомендуется для любого изменчивого типа (что, очевидно, это или это не будет проблемой!)

  2. Внедрите механизм «клонирования» для ваших типов. Это может быть ICloneable или даже просто конструктор, который принимает экземпляр и копирует значения из него.

  3. Используйте reflection, MemberwiseClone или аналогично, чтобы скопировать все значения, поэтому вам не нужно писать код для этого. У этого есть потенциальные проблемы, особенно если у вас есть поля, содержащие непростые типы.

То, что вы ищете, – это клонирование. Вам нужно будет выполнить IClonable, а затем выполнить Cloning.

Пример:

 class Person() : ICloneable { public string head; public string feet; #region ICloneable Members public object Clone() { return this.MemberwiseClone(); } #endregion } 

Затем вы можете просто вызвать метод Clone для создания ShallowCopy (в этом конкретном случае также DeepCopy )

 Person a = new Person() { head = "big", feet = "small" }; Person b = (Person) a.Clone(); 

Вы можете использовать метод MemberwiseClone classа Object для клонирования.

Для этого я использую AutoMapper. Он работает следующим образом:

 Mapper.CreateMap(typeof(Person), typeof(Person)); Mapper.Map(a, b); 

Теперь человек a обладает всеми свойствами человека b.

В отличие от AutoMapper работает и для разных объектов. Для получения дополнительной информации, ознакомьтесь с ней на http://automapper.org

Обновление: теперь я использую этот синтаксис (упрощенно – действительно, CreateMaps находятся в профилях AutoMapper):

 Mapper.CreateMap; Mapper.Map(a, b); 

Обратите внимание, что вам не нужно делать CreateMap для сопоставления одного объекта того же типа с другим, но если вы этого не сделаете, AutoMapper создаст мелкую копию, а это означает, что если человек изменит один объект, другой изменения также.

Поскольку метод MemberwiseClone () не является общедоступным, я создал этот простой метод расширения, чтобы упростить клонирование объектов:

 public static T Clone(this T obj) { var inst = obj.GetType().GetMethod("MemberwiseClone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); return (T)inst?.Invoke(obj, null); } 

Применение:

 var clone = myObject.Clone(); 

Чтобы клонировать объект classа, вы можете использовать метод Object.MemberwiseClone,

просто добавьте эту функцию в свой class:

 public class yourClass { // ... // ... public yourClass DeepCopy() { yourClass othercopy = (yourClass)this.MemberwiseClone(); return othercopy; } } 

то для выполнения глубокой независимой копии просто вызовите метод DeepCopy:

 yourClass newLine = oldLine.DeepCopy(); 

a и b – всего две ссылки на один и тот же объект Person. Они оба по существу имеют адрес Person .

Существует интерфейс ICloneable , хотя относительно небольшое число classов поддерживают его. При этом вы должны написать:

 Person b = a.Clone(); 

Тогда b будет полностью отдельным Person .

Вы также можете реализовать конструктор копирования:

 public Person(Person src) { // ... } 

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

Вы можете сделать это так:

 var jss = new JavaScriptSerializer(); var b = jss.Deserialize(jss.Serialize(a)); 

Для глубокого клонирования вы можете взглянуть на этот ответ: https://stackoverflow.com/a/78612/550975

  public static T Clone(T obj) { DataContractSerializer dcSer = new DataContractSerializer(obj.GetType()); MemoryStream memoryStream = new MemoryStream(); dcSer.WriteObject(memoryStream, obj); memoryStream.Position = 0; T newObject = (T)dcSer.ReadObject(memoryStream); return newObject; } 

Безболезненно: использование библиотеки NClone

 Person a = new Person() { head = "big", feet = "small" }; Person b = Clone.ObjectGraph(a); 

Это происходит потому, что «Лицо» – это class, поэтому он передается по ссылке. В заявлении «b = a» вы просто копируете ссылку на экземпляр «Человек», который вы создали с ключевым словом new.

Самый простой способ иметь поведение, которое вы ищете, это использовать «тип значения».

Просто измените объявление Person из

 class Person 

в

 struct Person 
  • Заменить все объекты NSNull в NSDictionary
  • Когда следует использовать nil и NULL в Objective-C?
  • Управление памятью в Qt?
  • Как вызвать метод Objective C из Javascript и отправить данные в Javascript в iOS?
  • Что такое экземпляр Java?
  • Заголовок песни iTunes Прокрутка в cocoa
  • С чем следует заменить устаревший метод sizeWithFont:?
  • Получить определенный объект из файла Rdata
  • В какой момент разыменование нулевого указателя становится неопределенным поведением?
  • Есть ли простой способ конвертировать метку времени ISO8601 в форматированный NSDate?
  • NSString для CFStringRef и CFStringRef для NSString в ARC?
  • Interesting Posts

    Сравнение поплавков и удвоений IEEE для равенства

    Как избежать ошибки из памяти при использовании растровых изображений в Android

    Как удалить ключ из HashMap, итерации по нему?

    Игра для DirectX 9, не работающая с DirectX 11

    Добавить ярлык в SmcFanControl?

    Аутентификация Active Directory с помощью Java на Linux

    Перекрытие просмотров в Android

    Как тег отличается от ветки в Git? Что я должен использовать здесь?

    Ошибка: в этом контексте поддерживаются только примитивные типы или типы перечислений EF

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

    ускорение амперсанда в URL-адресе

    Каковы некоторые причины, по которым NetworkStream.Read зависает / блокируется?

    Как я могу скомпилировать свой Perl-скрипт, чтобы он мог выполняться в системах без установленного perl?

    Как сбросить драйверы видео / дисплея в Vista без перезагрузки ОС?

    динамический xpath в xslt?

    Давайте будем гением компьютера.