我正在尝试优化克隆对象的一段代码:
#region ICloneable
public object Clone()
{
MemoryStream buffer = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(buffer, this); // takes 3.2 seconds
buffer.Position = 0;
return formatter.Deserialize(buffer); // takes 2.1 seconds
}
#endregion
非常标准的东西。问题是该对象非常强大,需要5.4秒(根据ANTS Profiler - 我确信有探查器开销,但仍然)。
有更好更快的克隆方法吗?
答案 0 :(得分:6)
不要实施ICloneable。
克隆对象的快速方法是创建相同类型的新实例,并将原始实例中的所有字段复制/克隆到新实例。不要试图提出可以克隆任何类的任何对象的“通用”克隆方法。
示例:
class Person
{
private string firstname;
private string lastname;
private int age;
public Person(string firstname, string lastname, int age)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
public Person Clone()
{
return new Person(this.firstname, this.lastname, this.age);
}
}
答案 1 :(得分:1)
据我所知,溪流,甚至是像这样的内流都很贵 您是否尝试过创建新对象并更新相关字段以使对象处于相同状态?我发现很难相信你的方法花费的时间更少。
答案 2 :(得分:1)
这是一种非常昂贵的克隆方式。对象永远不会出现在线上,所以一直进行序列化基本上都是浪费。成员克隆会更快。我意识到这不是一个自动化解决方案,但它会是最快的。
这些方面的东西:
class SuperDuperClassWithLotsAndLotsOfProperties {
object Clone() {
return new SuperDuperClassWithLotsAndLotsOfProperties {
Property1 = Property1,
Property2 = Property2,
}
public string Property1 {get;set;}
public string Property2 {get;set;}
}
}
答案 3 :(得分:1)
因为手动复制字段是我创建代码生成器的最快方法,它会读取您的类定义并生成克隆方法。您所需要的只是CGbR nuget package和实现ICloneable
的部分类。发电机将完成其余的工作。
public partial class Root : ICloneable
{
public Root(int number)
{
_number = number;
}
private int _number;
public Partial[] Partials { get; set; }
public IList<ulong> Numbers { get; set; }
public object Clone()
{
return Clone(true);
}
private Root()
{
}
}
public partial class Root
{
public Root Clone(bool deep)
{
var copy = new Root();
// All value types can be simply copied
copy._number = _number;
if (deep)
{
// In a deep clone the references are cloned
var tempPartials = new Partial[Partials.Length];
for (var i = 0; i < Partials.Length; i++)
{
var value = Partials[i];
value = value.Clone(true);
tempPartials[i] = value;
}
copy.Partials = tempPartials;
var tempNumbers = new List<ulong>(Numbers.Count);
for (var i = 0; i < Numbers.Count; i++)
{
var value = Numbers[i];
tempNumbers[i] = value;
}
copy.Numbers = tempNumbers;
}
else
{
// In a shallow clone only references are copied
copy.Partials = Partials;
copy.Numbers = Numbers;
}
return copy;
}
}
和部分类
public partial class Partial : ICloneable
{
public short Id { get; set; }
public string Name { get; set; }
public object Clone()
{
return Clone(true);
}
}
public partial class Partial
{
public Partial Clone(bool deep)
{
var copy = new Partial();
// All value types can be simply copied
copy.Id = Id;
copy.Name = Name;
return copy;
}
}
答案 4 :(得分:0)
答:有更好的克隆方法。
反射或表达式树比序列化快得多(反射快5倍,表达式树<强>快20倍)。
如果您使用 this linked cloning function 作为扩展方法,则每个克隆代码都缩小为
#region ICloneable
public object Clone()
{
return this.DeepCopyByExpressionTree();
}
#endregion
要使用扩展方法,只需在解决方案中的任何位置放置 DeepCopyByExptressionTrees.cs 文件即可。