Deep copy of C # object

I am working on some code written in C #. In this application, I have a custom collection defined as follows:

public class ResultList<T> : IEnumerable<T> { public List<T> Results { get; set; } public decimal CenterLatitude { get; set; } public decimal CenterLongitude { get; set; } } 

The type used by Results is one of three custom types. The properties of each of the custom types are simply primitive types (ints, string, bools, int ?, bool?). The following is an example of one of the custom types:

 public class ResultItem { public int ID { get; set; } public string Name { get; set; } public bool? isLegit { get; set; } } 

How to make a deep copy of the ResultList object that I created. I found this post: General method of creating a deep copy of all elements in a collection . However, I cannot figure out how to do this.

+6
source share
4 answers

One of the reasons why your ResultList class will not work with Jon Skeet is because it does not implement the ICloneable interface.

Implement ICloneable for all classes you need to clone, e.g.

 public class ResultItem : ICloneable { public object Clone() { var item = new ResultItem { ID = ID, Name = Name, isLegit = isLegit }; return item; } } 

And also in ResultList:

 public class ResultList<T> : IEnumerable<T>, ICloneable where T : ICloneable { public List<T> Results { get; set; } public decimal CenterLatitude { get; set; } public decimal CenterLongitude { get; set; } public object Clone() { var list = new ResultList<T> { CenterLatitude = CenterLatitude, CenterLongitude = CenterLongitude, Results = Results.Select(x => x.Clone()).Cast<T>().ToList() }; return list; } } 

Then make a deep copy of your object:

 resultList.clone(); 
+8
source

The least coding effort is the process of serializing and deserializing through BinaryFormatter .

You can define the following extension method (taken from Kilhoffers answer ):

 public static T DeepClone<T>(T obj) { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; return (T)formatter.Deserialize(ms); } } 

... and then just call:

 ResultList<T> clone = DeepClone(original); 
+12
source

Extending to @ Georgi-it, I had to change its code to handle properties whose type inherits from List:

 public static class ObjectCloner { public static T Clone<T>(object obj, bool deep = false) where T : new() { if (!(obj is T)) { throw new Exception("Cloning object must match output type"); } return (T)Clone(obj, deep); } public static object Clone(object obj, bool deep) { if (obj == null) { return null; } Type objType = obj.GetType(); if (objType.IsPrimitive || objType == typeof(string) || objType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == 0) == null) { return obj; } List<PropertyInfo> properties = objType.GetProperties().ToList(); if (deep) { properties.AddRange(objType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)); } object newObj = Activator.CreateInstance(objType); foreach (var prop in properties) { if (prop.GetSetMethod() != null) { var proceed = true; if (obj is IList) { var listType = obj.GetType().GetProperty("Item").PropertyType; if (prop.PropertyType == listType) { proceed = false; foreach (var item in obj as IList) { object clone = Clone(item, deep); (newObj as IList).Add(clone); } } } if (proceed) { object propValue = prop.GetValue(obj, null); object clone = Clone(propValue, deep); prop.SetValue(newObj, clone, null); } } } return newObj; } } 
+3
source

Here is what I need and wrote, it uses reflection to copy each property (and private if specified)

 public static class ObjectCloner { public static T Clone<T>(object obj, bool deep = false) where T : new() { if (!(obj is T)) { throw new Exception("Cloning object must match output type"); } return (T)Clone(obj, deep); } public static object Clone(object obj, bool deep) { if (obj == null) { return null; } Type objType = obj.GetType(); if (objType.IsPrimitive || objType == typeof(string) || objType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == 0) == null) { return obj; } List<PropertyInfo> properties = objType.GetProperties().ToList(); if (deep) { properties.AddRange(objType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)); } object newObj = Activator.CreateInstance(objType); foreach (var prop in properties) { if (prop.GetSetMethod() != null) { object propValue = prop.GetValue(obj, null); object clone = Clone(propValue, deep); prop.SetValue(newObj, clone, null); } } return newObj; } } 
+1
source

Source: https://habr.com/ru/post/918300/


All Articles