我一直在为一个项目创建对象,并且有一些示例需要为这些对象创建一个深层副本。我想到了使用C#的一个内置函数,即MemberwiseClone。().困扰我的问题是每当我创建了一个新类时,我将不得不写一个函数一样的代码下面的浅层副本..有人可以请帮我改善这一部分,给予我一个浅层副本,比第二行代码更好。谢谢你:)
浅文本:
public static RoomType CreateTwin(RoomType roomType)
{
return (roomType.MemberwiseClone() as RoomType);
}
深层文本:
public static T CreateDeepClone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
3条答案
按热度按时间0yg35tkg1#
MemberwiseClone不是执行深层复制(MSDN)的好选择:
MemberwiseClone方法通过创建新对象,然后将当前对象的非静态字段复制到新对象来创建浅层副本。如果字段是值类型,则执行字段的逐位复制。如果字段是引用类型,则复制引用,但不复制被引用的对象;因此,原始对象及其克隆引用同一对象。
这意味着如果克隆对象具有引用类型公共字段或属性,它们将引用与原始对象的字段/属性相同的内存位置,因此克隆对象中的每个更改都将反映在初始对象中。这不是真正的深层复制。
您可以使用BinarySerialization建立对象的完全独立执行严修,如需序列化范例,请参阅BinaryFormatter class的MSDN Page。
示例和测试工具:
创建给定对象深层副本的扩展方法:
N单元测试:
pkmbmrz72#
您也可以使用反映来建立对象的复本,这应该是最快的方式,因为序列化也会使用反映。
下面是一些代码(经过测试):
更新
添加了一些代码,现在可以使用方法复制复杂对象(甚至是多维数组)。请注意,委托仍然没有实现。
如果你想要一个完整的实现,你需要处理
ISerializable
接口,这并不是很难,但是需要一些时间来反映现有的代码。aamkag613#
正如sll所建议的,使用序列化的解决方案是目前为止最简单的,但是如果您试图克隆的类型是不可序列化的,则该解决方案不起作用。
Felix K.的代码是一个很好的替代方案,但是我发现了一些问题。这里是一个修订版,修复了我发现的一些问题。我还删除了一些我不需要的功能(例如,构造函数参数)。