复制一个类,C#

有没有办法在C#中复制一个类? 像var dupe = MyClass(original)之类的东西。

您可能正在谈论深层复制( 深拷贝与浅拷贝 )?

你要么:

  1. 实现(硬编码)你自己的方法,
  2. 尝试实现(或找到)使用Reflection或Emit动态执行它的实现( 在此解释),
  3. 如果对象标有[Serializable]属性,则使用序列化和反序列化来创建深层副本。
 public static T DeepCopy(T other) { using (MemoryStream ms = new MemoryStream()) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(ms, other); ms.Position = 0; return (T)formatter.Deserialize(ms); } } 

要获得浅表副本,可以使用Object.MemberwiseClone()方法,但它是受保护的方法,这意味着您只能在类中使用它。

对于所有深度复制方法,重要的是要考虑对其他对象的引用,或者循环引用,这可能导致创建比您想要的更深的副本。

并非所有类都具有此function。 可能,如果一个类,它提供了一个Clone方法。 为了帮助为您自己的类实现该方法,在System.Object中定义了一个MemberwiseClone保护方法,该方法生成当前实例的浅表副本(即复制字段;如果它们是引用类型,则引用将指向原始位置)。

如果你的class级刚刚获得了属性,你可以这样做:

 SubCentreMessage actual; actual = target.FindSubCentreFullDetails(120); //for Albany SubCentreMessage s = new SubCentreMessage(); //initialising s with the same values as foreach (var property in actual.GetType().GetProperties()) { PropertyInfo propertyS = s.GetType().GetProperty(property.Name); var value = property.GetValue(actual, null); propertyS.SetValue(s, property.GetValue(actual, null), null); } 

如果您有字段和方法,我相信您可以使用reflection在新类中重新创建它们。 希望这可以帮助

是的,不是。 这是一个你需要小心的区域,因为有一些陷阱(然后再次,这并不困难)。

首先,如果您在基类库(BCL)中稍微探讨一下,您可能会发现ICloneable接口 。 并非所有类型都实现此接口,但那些具有Clone方法的接口将返回相同类型的新实例(可能)具有相同的值。

但是,这里有一个陷阱:ICloneable接口没有充分指定是否需要深度克隆或浅层克隆,因此一些实现做了一件事,而其他实现则做另一件事。 出于这个原因,ICloneable使用不多,并且不鼓励进一步使用它 – 请参阅优秀的框架设计指南以获取更多详细信息。

如果深入挖掘BCL,您可能会发现System.Object具有受保护的MemberwiseClone方法。 虽然您无法直接从其他类型调用此方法,但您可以使用此方法在您自己的对象中实现克隆。

常见的克隆模式是定义要克隆的类的受保护构造函数,并将已存在的实例作为参数传递。 像这样的东西:

 public class MyClass() { public MyClass() {} protected MyClass(MyClass other) { // Cloning code goes here... } public MyClass Clone() { return new MyClass(this); } } 

但是,这显然只有在您控制要克隆的类型时才有效。

如果要克隆无法修改的类型,并且不提供克隆方法,则需要编写代码以将每个数据从旧实例显式复制到新实例。

我认为作者正在询问复制构造函数……

答案是“是的,但只有你自己实现它”,没有“自动”的方式,没有一些沉重的条件(读取:reflection):

 class MyClass { private string _name; // standard constructor, so that we can make MyClass's without troubles public MyClass(string name) {_name = name} public MyClass(MyClass old) { _name = old._name; // etc... } } 

在这方面需要注意的另一件事是IClonable接口,以及它提供的.Clone()方法。 另外.MemberwiseClone()类提供的.MemberwiseClone()保护方法可以帮助实现这两种方法。

用JSON怎么样?

您可以从以下url获取JSON包: https : //www.nuget.org/packages/Newtonsoft.Json/

 using Newtonsoft.Json; public static List CopyAll(this List list) { List ret = new List(); string tmpStr = JsonConvert.SerializeObject(list); ret = JsonConvert.DeserializeObject>(tmpStr); return ret; } 

不是任何直截了当的方式总能奏效。 如果您的类是[Serializable]或实现ISerializable ,您可以执行往返序列化以创建相同的副本。 [DataContract]同样适用

如果您只想要浅拷贝,可以尝试Object.MemberwiseClone() 。 这是一个受保护的方法,你只能在课堂上使用它。

如果你很幸运,该类实现了ICloneable ,你可以调用Clone()方法。

一种可能性是克隆它。 您必须实现ICloneable接口和Clone方法。

你的意思是复制构造函数,就像它存在于C ++中一样?

它在C#中不存在。 您可以做的是编写自己的(这是单调乏味的),或者您可以编写一个’克隆’方法,该方法使用序列化来创建一个与原始类具有完全相同值的新实例。

您可以序列化当前实例,对其进行反序列化,然后返回反序列化的结果。 缺点是您的类必须是Serializable。

克隆对象的简单方法是将其写入流并再次读取:

 public object Clone() { object clonedObject = null; BinaryFormatter formatter = new BinaryFormatter(); using (Stream stream = new MemoryStream()) { formatter.Serialize(stream, this); stream.Seek(0, SeekOrigin.Begin); clonedObject = formatter.Deserialize(stream); } return clonedObject; } 

但请注意,这可能会导致所谓的聚合对象出现问题。

怎么样的:

 public class MyClass { int i; double d; string something; public MyClass(int i, double d) {} public MyClass Clone() { return (new MyClass(i, d)); } } 

或者,如果您还需要复制构建新对象时通常不知道的其他内容:

  public MyClass CloneMore() { MyClass obj = new MyClass(i, d); obj.something = this.something; return (obj); } 

使用呼叫:

 MyClass us = them.Clone(); 

~~~

这里序列化的一些合理的解决方案是一个有效的方法来解决它以及每个类的克隆方法..鞭打它,它似乎适用于我做的几个测试

 using System.Reflection; using System.Text.StringBuilder(); public static T CopyClass2(T obj){ T objcpy = (T)Activator.CreateInstance(typeof(T)); obj.GetType().GetProperties().ToList() .ForEach( p => objcpy.GetType().GetProperty(p.Name).SetValue(objcpy, p.GetValue(obj))); return objcpy; 

}

这里是我认为的更冗长的版本,上面建议您理解Lambda表达式并不常见。 如果你尊重可读性(这是完全有效的),我会在下面使用

 public static T CopyClass(T obj) { T objcpy = (T)Activator.CreateInstance(typeof(T)); foreach (var prop in obj.GetType().GetProperties()) { var value = prop.GetValue(obj); objcpy.GetType().GetProperty(prop.Name).SetValue(objcpy, value); } return objcpy; 

}

使用此方法列出属性以查看它是否复制到新引用…简单它没有列出none基元的属性(结构化类型)..所以你将得到一个类名

 public static string ListAllProperties(T obj) { StringBuilder sb = new System.Text.StringBuilder(); PropertyInfo[] propInfo = obj.GetType().GetProperties(); foreach (var prop in propInfo) { var value = prop.GetValue(obj) ?? "(null)"; sb.AppendLine(prop.Name + ": " + value.ToString()); } return sb.ToString(); }