|
|
1
1556
而标准做法是实施
正如在别处提到的,它确实要求您的对象是可序列化的。
其思想是将对象序列化,然后将其反序列化为新对象。好处是,当对象变得过于复杂时,您不必担心克隆任何东西。 以及使用扩展方法(也来自最初引用的源): 如果你喜欢用新的 extension methods 对于C 3.0,将方法更改为具有以下签名:
现在方法调用简单地变成
编辑 (2015年1月10日)我想重新审视一下这个问题,更重要的是我最近开始使用(newtonsoft)json来做这个,它 should be 更轻,并且避免了[serializable]标记的开销。( 铌 @atconway在评论中指出私有成员不是使用json方法克隆的)
|
|
|
2
217
我想要一个克隆器来克隆非常简单的对象,其中大部分都是原语和列表。如果您的对象是开箱即用的可序列化JSON,那么这个方法就可以做到这一点。这不需要修改或实现克隆类上的接口,只需要像json.net这样的JSON序列化程序。
另外,您可以使用这个扩展方法
|
|
|
3
161
不使用的原因 ICloneable 是 不 因为它没有通用接口。 The reason not to use it is because it's vague . 它不清楚您得到的是一个浅薄的还是一个深刻的副本;这取决于实现者。
对,
我通常做的就是
|
|
|
4
99
我相信,在阅读了大量关于这里所链接的许多选项以及这个问题的可能解决方案的文章之后, all the options are summarized pretty well at Ian P 's link (所有其他选项都是这些选项的变体)最佳解决方案由 Pedro77 's link 关于问题的评论。 所以我将在这里复制这两个参考文献的相关部分。这样我们就可以: 在C夏普中克隆对象的最佳方法!首先,这些都是我们的选择:
这个 article Fast Deep Copy by Expression Trees 通过序列树、反射树和表达式树对克隆的性能进行了比较。 为什么我选择 可逗留的 (即手动)Mr Venkat Subramaniam (redundant link here) explains in much detail why . 他的所有文章都围绕着一个试图适用于大多数情况的示例,使用3个对象: 人 , 脑 和 西蒂 . 我们想克隆一个人,他将有自己的大脑,但同样的城市。您可以想象所有的问题,上面的任何其他方法都可以带来或阅读这篇文章。 这是我对他的结论稍加修改的版本:
希望这个实现可以使事情变得清楚:
现在考虑让一个类从人派生。
您可以尝试运行以下代码:
产生的输出将是:
注意,如果我们对对象的数量进行计数,这里实现的克隆将对对象的数量进行正确的计数。 |
|
5
76
比起克隆,我更喜欢复制构造函数。目的更加明确。 |
|
|
6
38
复制所有公共属性的简单扩展方法。适用于任何对象和
不
要求类为
|
|
|
7
30
我在Silverlight中使用icloneable时遇到了一些问题,但是我喜欢seravization的思想,我可以将XML seravizing,所以我这样做了:
|
|
|
8
26
我刚刚创造了
如何使用?
而不是自己写
您可以选择要从中复制的内容
什么可以克隆?
以下类/结构成员在内部克隆:
它有多快?
解决方案比反射更快,因为成员信息必须在
当克隆多个相同类型的实例时,它也比基于序列化的解决方案更快。
还有更多… 阅读有关上生成的表达式的详细信息 documentation .
示例表达式调试列表
} 以下C代码的含义相同:
这不是很像你自己写的吗
|
|
|
9
26
如果您已经在使用第三方应用程序,例如 ValueInjecter 或 Automapper ,您可以这样做:
使用此方法,您不必在对象上实现ISerializable或IClonable。这在MVC/MVVM模式中很常见,因此已经创建了类似这样的简单工具。 |
|
|
10
20
简短的回答是,您从ICloneable接口继承,然后实现.clone函数。克隆应执行memberwise复制,并对任何需要它的成员执行深度复制,然后返回结果对象。这是一个递归操作(它要求要克隆的类的所有成员要么是值类型,要么是实现ICloneable,并且它们的成员要么是值类型,要么是实现ICloneable,依此类推)。 有关使用icloneable克隆的详细说明,请查看 this article . 这个 长的 答案是“视情况而定”。正如其他人所提到的,icloneable不受泛型的支持,需要对循环类引用进行特殊考虑,并且实际上被一些人视为 "mistake" 在.NET框架中。序列化方法取决于要序列化的对象,这些对象可能不是,您可能无法控制。在社区中,关于“最佳”实践的争论仍然很多。实际上,没有一个解决方案是适用于所有情况的“一刀切”最佳实践,就像最初解释的icloneable那样。 看到这个 Developer's Corner article 为了更多的选择(归功于伊恩)。 |
|
|
11
17
最好是实现 扩展方法 喜欢
然后在解决方案中的任何位置使用它
我们可以有以下三种实现:
所有的连接方法都工作良好,并经过了深入的测试。 |
|
|
12
16
干杯。 |
|
|
13
15
如果你想真正克隆到未知类型,你可以看看 fastclone . 这是基于表达式的克隆,其工作速度比二进制序列化快10倍,并且保持了完整的对象图完整性。 这意味着:如果在层次结构中多次引用同一对象,克隆也将引用一个实例。 不需要对要克隆的对象进行接口、属性或任何其他修改。 |
|
|
14
11
简单易用 AutoMapper 正如其他人提到的,它是一个简单的小库,可以将一个对象映射到另一个对象…要将一个对象复制到另一个具有相同类型的对象,只需要三行代码:
目标对象现在是源对象的副本。 不够简单?创建扩展方法以在解决方案中的任何位置使用:
通过使用扩展方法,三条线变为一条线:
|
|
15
10
我想出这个来克服 .NET 缺点是必须手动深度复制列表<t>。 我用这个:
在另一个地方:
我尝试使用一个行程序来实现这一点,但这是不可能的,因为在匿名方法块中不工作。 更好的是,使用通用列表<t>克隆器:
|
|
|
16
7
通常,您实现ICloneable接口并自己实现克隆。 C对象有一个内置的memberWiseClone方法,它执行一个浅拷贝,可以帮助您完成所有原语。 对于深度复制,它不可能知道如何自动执行。 |
|
|
17
7
我也看到它是通过反射实现的。基本上,有一个方法可以迭代对象的成员,并将它们适当地复制到新对象。当它到达引用类型或集合时,我认为它对自身进行了递归调用。反射是昂贵的,但效果很好。 |
|
|
18
7
下面是一个深度复制实现:
|
|
|
19
7
问:我为什么要选择这个答案?
比其他方法快10倍执行深度克隆的以下方法是:
方法……对于终极速度,您可以使用 嵌套的MemberWiseClone执行深度复制 . 它几乎与复制值结构的速度相同,并且比(a)反射或(b)序列化(如本页其他答案中所述)快得多。 注意 如果 你用 用于深度复制的嵌套MemberWiseClone ,您必须为类中的每个嵌套级别手动实现一个Shallowcopy,以及一个调用所有上述Shallowcopy方法以创建完整克隆的deepcopy。这很简单:总共只有几行,请参见下面的演示代码。 下面是显示100000个克隆的相对性能差异的代码输出:
在类上使用嵌套的MemberWiseClone的速度几乎与复制结构的速度相同,并且复制结构的速度非常接近理论上.NET所能达到的最大速度。
要了解如何使用memberwisecopy进行深度复制,下面是用于生成上述时间的演示项目:
然后,从MAIN调用演示:
同样,请注意 如果 你用 用于深度复制的嵌套MemberWiseClone ,您必须为类中的每个嵌套级别手动实现一个Shallowcopy,以及一个调用所有上述Shallowcopy方法以创建完整克隆的deepcopy。这很简单:总共只有几行,请参见上面的演示代码。 值类型与引用类型请注意,在克隆对象时,在 结构 “和” 班 “:
见 值类型和引用类型之间的差异 . 帮助调试的校验和
对于将多个线程与许多其他线程分离非常有用此代码的一个很好的用例是将嵌套类或结构的克隆提供到队列中,以实现生产者/使用者模式。
这在实践中非常有效,并且允许我们将多个线程(生产者)与一个或多个线程(消费者)分离。 这个方法也非常快:如果我们使用嵌套结构,它比序列化/反序列化嵌套类快35倍,并且允许我们利用机器上所有可用的线程。 更新显然,ExpressMapper的速度(如果不是更快的话)与上面的手工编码一样快。我可能需要看看它们如何与分析器进行比较。 |
|
|
20
7
由于在不同的项目中找不到满足我所有需求的克隆器,所以我创建了一个深度克隆器,它可以配置和适应不同的代码结构,而不是修改我的代码来满足克隆器的需求。它是通过在应该克隆的代码中添加注释来实现的,或者您只需保持代码的默认行为。它使用反射、类型缓存并基于 fasterflect . 对于大量数据和高对象层次结构(与其他基于反射/序列化的算法相比),克隆过程非常快。 https://github.com/kalisohn/CloneBehave 也可作为Nuget软件包提供: https://www.nuget.org/packages/Clone.Behave/1.0.0 例如:下面的代码将DEEPCLONE ADDRESS,但只执行_currentJob字段的浅拷贝。
|
|
21
6
这种方法解决了我的问题:
这样使用:
|
|
|
22
5
我喜欢这样的复制构造器:
如果有更多的东西要复制,请添加它们 |
|
|
23
5
代码生成器我们已经看到了很多想法,从手工实现的序列化到反思,我想提出一种完全不同的方法,使用 CGbR Code Generator . generate clone方法具有内存和CPU效率,因此比标准的DataContractSerializer快300倍。
你只需要一个部分类定义
注: 最新的版本有更多的空检查,但为了更好地理解,我省略了它们。 |
|
24
5
这里有一个快速而简单的解决方案,它在不中继序列化/反序列化的情况下为我工作。
编辑 : 要求
我就是这么用的
|
|
|
25
4
遵循以下步骤:
为了获得最大的继承多功能性,公开公共克隆功能的类应该是
|
|
|
26
4
我想你可以试试这个。
|
|
|
27
3
我已经创建了一个可与'[serializable]'和'[datacontract]'同时使用的接受回答版本。我写它已经有一段时间了,但是如果我正确地记得[datacontract]需要一个不同的序列化程序。 要求 系统,system.io,system.runtime.serialization,system.runtime.serialization.formatters.binary,system.xml ;
|
|
|
28
3
要克隆类对象,可以使用object.memberWiseClone方法, 只需将此函数添加到类中:
然后,要执行深度独立复制,只需调用deep copy方法:
希望这有帮助。 |
|
|
29
3
好的,这篇文章中有一些关于反射的明显例子,但是反射通常很慢,直到您开始正确地缓存它。 如果您能正确地缓存它,那么它将以4,6秒(由观察者测量)深度克隆1000000个对象。
而不是将缓存属性或新属性添加到字典并简单地使用它们
完整的代码在我的帖子中签入另一个答案 |
|
|
30
3
如果对象树是可序列化的,则也可以使用类似的内容
请注意,此解决方案非常简单,但其性能不如其他解决方案。 并且确保如果类增长,那么仍然只有克隆的字段,这些字段也将被序列化。 |
|
|
A B · C#Excel自动调整列避免长文本时出错 1 年前 |
|
|
Megrez7 · C#ToArray转换合并为一行,导致数组元素更改 1 年前 |
|
Aycon · 在工厂方法中释放部分创建的对象的正确方法是什么? 1 年前 |
|
|
Sei · Avalonia/WPF将路由器传递到控制模板 1 年前 |