📜  c# 复制一个对象 - C# (1)

📅  最后修改于: 2023-12-03 15:29:47.114000             🧑  作者: Mango

C# 复制一个对象

在 C# 中,我们可以使用两种方法来复制对象:浅复制和深复制。

浅复制

浅复制是指复制对象时只复制其成员变量的值,而不是复制其引用类型变量所引用的对象。换言之,浅复制会复制引用类型变量的地址,这样两个对象会引用相同的对象,只是使用的变量名不同。

我们可以通过重载对象的 Clone() 方法来实现浅复制。以下是一个示例:

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }

    public Person Clone()
    {
        return (Person)this.MemberwiseClone();
    }
}

class Address
{
    public string City { get; set; }
    public string State { get; set; }
}

// 测试代码
Person a = new Person() { Name = "Alice", Age = 20, Address = new Address() { City = "New York", State = "NY" } };
Person b = a.Clone();

Console.WriteLine($"a: {a.Name} ({a.Age}), {a.Address.City}, {a.Address.State}");
Console.WriteLine($"b: {b.Name} ({b.Age}), {b.Address.City}, {b.Address.State}");

a.Name = "Bob";
a.Age = 30;
a.Address.City = "Seattle";
a.Address.State = "WA";

Console.WriteLine($"a: {a.Name} ({a.Age}), {a.Address.City}, {a.Address.State}");
Console.WriteLine($"b: {b.Name} ({b.Age}), {b.Address.City}, {b.Address.State}");

输出结果:

a: Alice (20), New York, NY
b: Alice (20), New York, NY
a: Bob (30), Seattle, WA
b: Alice (20), Seattle, WA

可以发现,虽然 ab 最初的值是相同的,但是当我们修改 a 的属性时,b 并未跟着变化,因为它们引用的是不同的 Address 对象。

需要注意的是,Clone() 方法默认是浅复制,因此如果对象中包含引用类型的成员变量,则需要在 Clone() 方法中对其进行深复制。

深复制

深复制是指复制对象时不仅复制其成员变量的值,还会复制其引用类型变量所引用的对象。这样,两个对象引用的是不同的对象,修改其中一个对象不会影响另一个对象。

实现深复制有多种方法,其中一个简单的方法是将对象序列化为字节数组,然后再反序列化得到一个新的对象。以下是一个示例:

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }

    public Person DeepClone()
    {
        using (MemoryStream stream = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, this);
            stream.Seek(0, SeekOrigin.Begin);
            return (Person)formatter.Deserialize(stream);
        }
    }
}

class Address
{
    public string City { get; set; }
    public string State { get; set; }
}

// 测试代码
Person a = new Person() { Name = "Alice", Age = 20, Address = new Address() { City = "New York", State = "NY" } };
Person b = a.DeepClone();

Console.WriteLine($"a: {a.Name} ({a.Age}), {a.Address.City}, {a.Address.State}");
Console.WriteLine($"b: {b.Name} ({b.Age}), {b.Address.City}, {b.Address.State}");

a.Name = "Bob";
a.Age = 30;
a.Address.City = "Seattle";
a.Address.State = "WA";

Console.WriteLine($"a: {a.Name} ({a.Age}), {a.Address.City}, {a.Address.State}");
Console.WriteLine($"b: {b.Name} ({b.Age}), {b.Address.City}, {b.Address.State}");

输出结果:

a: Alice (20), New York, NY
b: Alice (20), New York, NY
a: Bob (30), Seattle, WA
b: Alice (20), New York, NY

可以发现,b 的值没有跟着变化,这是因为 a.DeepClone() 创建了一个新的对象,与 a 没有关系。

需要注意的是,在实现 DeepClone() 方法时,需要保证对象及其成员变量是可序列化的。