引用類型字段淺拷貝導致副本共享子對象,修改相互影響。需深拷貝完全隔離。
public class Shoe : ICloneable
{
public string Color;
public object Clone() => new Shoe { Color = (string)Color.Clone() };
}
public class Dude : ICloneable
{
public string Name;
public Shoe LeftShoe, RightShoe;
public object Clone()
{
return new Dude
{
Name = (string)Name.Clone(),
LeftShoe = (Shoe)LeftShoe.Clone(),
RightShoe = (Shoe)RightShoe.Clone()
};
}
}
Dude bill = new Dude { Name = "Bill", LeftShoe = new Shoe { Color = "Blue" }, RightShoe = new Shoe { Color = "Blue" } };
Dude ted = (Dude)bill.Clone();
ted.Name = "Ted";
ted.LeftShoe.Color = ted.RightShoe.Color = "Red";
Console.WriteLine(bill); // Bill: Blue / Blue
Console.WriteLine(ted); // Ted: Red / Red
string 是引用類型,但不可變:任何「修改」操作都返回新實例。string s1 = "abc"; string s2 = s1; s2 = "def"; 不會影響 s1。string 實現了 ICloneable,Clone() 返回自身(因為不可變,無需複製)。ICloneable 時文檔說明是深拷貝還是淺拷貝(接口未強制規定)。readonly 字段、init 屬性、record),從根本避免拷貝問題。MemberwiseClone + 手動深拷貝引用字段、Expression 樹構建拷貝委託。IEquatable、GetHashCode 穩定)。