如何克隆具有已设置的所有值的类?

时间:2013-12-19 19:38:02

标签: c# .net

类示例:

public class Customer
{
    public int CustomerID { get; set; }
}

使用课程:

    Customer customer1 = new Customer();
    customer1.CustomerID = 1;

现在如何创建一个customer2类,其中包含存储在customer1中的所有值?

4 个答案:

答案 0 :(得分:6)

您可以手动执行此操作:

var customer2 = new Customer { CustomerID = customer1.CustomerID };

您可以在ICloneable类中实现Customer接口:

public class Customer : ICloneable
{
    private int CustomerID { get; set; }

    public Customer Clone()
    {
        return new Customer { CustomerID = this.CustomerID };
    }

    object ICloneable.Clone()
    {
        return this.Clone();
    }
}

然后使用它:

var customer2 = customer1.Clone();

您可以将对象序列化为XML / JSON,然后将其反序列化为新对象,如本答案中所述:Deep cloning objects in C#

或者您可以使用反射来获取并将所有属性/字段值复制到新的Customer实例中。它可能会有糟糕的表现,但您必须对其进行测量以确定它有多糟糕。

修改

还有一种方法:使用Expression Tree可以更快地制作反射版本!获取所有字段/属性,并使用Expression.Lambda在运行时编译所有必要的分配。之后,每个下一个Clone调用都将使用已编译的代码,因此根本没有性能缺陷。我已经使用Clone<T>类,静态构造函数和反射创建了Expression扩展方法。您可以在CodePlex上找到代码:CloneExtension.cs

答案 1 :(得分:1)

您可以使用反射来复制值,也可以使用深度克隆(ICloneable)。

答案 2 :(得分:1)

要扩展Marcin's answer,如果您班级中的所有项目都是值类型或不可变类型(intdoublestring等,那么您可以使用MemberwiseClone()。这将创建原始对象的shallow copy,如果所有成员都是不可变的,则无需执行深层复制。如果您需要复制类中的许多对象,这可能很有用。

public sealed class Customer : ICloneable
{
    private int CustomerID { get; set; }

    public Customer Clone()
    {
        return (customer)this.MemberwiseClone();
    }

    object ICloneable.Clone()
    {
        return this.Clone();
    }
}

答案 3 :(得分:0)

如果你像这样设置课程怎么办:

public class Customer
{
  private Customer Parent {get; private set;}

  private int _id;
  public int CustomerID
  {
    get { return Parent == null ? _id : Parent.CustomerID; }
    set
    {
      if(Parent != null)
        throw new InvalidOperationException("...");

      _id = value;
    }

    public Customer()
    {
    }

    public static Customer Clone(Customer parent)
    {
      return new Customer{Parent = parent};
    }
}

这将创建一个不可变的克隆。现在......如果你需要能够改变价值......那么要么采取不同的方法,要么扩展它。