复制类时创建类的新实例

本文关键字:实例 创建 复制 新实例 | 更新日期: 2023-09-27 18:09:19

我有一个这样的类:

Public Class Dog{
   public Dog(string name, int age){
      Name = name;
      Age = age;
   }
   public string Name { get; set; }
   public int Age { get; set; }
}

然后创建这个类的实例

Dog jake = new Dog("Jake", 3);

当我试图复制类并改变它的属性时,比如

Dog buster = jake;
buster.Name = "Buster";

当我这样做的时候,jake中的Name也会改变

我怎样才能避免这种情况?

请注意,我正在使用的类包含如此多的属性,如果我可以复制类并更改我想要的一个属性,这将使我更容易。

复制类时创建类的新实例

这是因为c#中内存的工作方式。每个类对象实际上都是指向内存中对象的指针——当你将一个变量赋值给另一个变量时,你仍然在使用同一个指针,因此,当你对一个对象进行更改时,修改的是相同的数据。

从技术上讲,如果你把所有的对象都做成结构,它们就可以很好地进行复制,因为结构是值类型,因此可以传递副本。然而,这是非常不可取的,因为它限制了使用,特别是对于多态性,并且对于具有许多成员的对象的内存管理是一个坏主意。

解决这个问题的最好方法是在类Dog上实现一个函数,允许你将数据复制到一个新的Dog对象中。因此,您将调用
Dog buster = jake.Clone();
buster.Name = "Buster";

在Clone中,将当前Dog对象的所有属性复制到一个新的Dog对象中。

编辑:回到c++的根,实现一个"复制构造函数"也很常见,它接受相同类型的参数并进行深度复制。即

Dog jake = new Dog() { Name = "Jake" };
Dog buster = new Dog(jake) { Name = "Buster" };

注意:上面的语法使用了花括号,它允许您在创建类时设置类的属性和字段。虽然从技术上讲编译器很简单,但它非常擅长使实例化调用更加简洁

以@Aravol提供的答案为基础,如果您有许多属性,您可以查看使用反射获取/设置克隆对象中的属性,以从您正在克隆的对象中获取属性的值。请看这里:

我可以用反射设置属性值吗?

当你做Dog buster = jake。创建一个指向jake的变量

所以当你执行buster.name = buster时,你实际上是在改变杰克的名字