C# 什么';s克隆方法之间的差异,并直接将实例分配给另一个

C# 什么';s克隆方法之间的差异,并直接将实例分配给另一个,c#,clone,C#,Clone,我想知道,如果我有一个名为Test的类,下面的区别是什么 Test test = new Test(); Test newTest = test; Test newTest2 = test.Clone(); 新测试和新测试2有什么不同? 有人能帮忙吗? 提前谢谢 Test newTest = test; 由于Test是一个引用类型(类),newTest现在引用与Test相同的对象。如果更改对象test引用,这将反映在newTest中,因为它们都引用同一对象 Test newTest2 = t

我想知道,如果我有一个名为Test的类,下面的区别是什么

Test test = new Test();
Test newTest = test;
Test newTest2 = test.Clone();
新测试和新测试2有什么不同? 有人能帮忙吗? 提前谢谢

Test newTest = test;
由于Test是一个引用类型(类),
newTest
现在引用与
Test
相同的对象。如果更改对象
test
引用,这将反映在
newTest
中,因为它们都引用同一对象

Test newTest2 = test.Clone();

假设
Clone()
返回一个新实例并进行深度复制(具体取决于您的实现),
newTest2
引用的是一个完全独立的对象,
test
中的任何更改都不会影响它。

当您分配实例时,如果
test
是一个类,实际上您正在复制引用,但是
test
newTest
都将指向内存中的同一实例

这意味着两个变量都指向同一个对象:

Test test = new Test();
test.Foo = 24;
Test newTest = test;
newTest.Foo = 42;
Console.WriteLine(test.Foo); // Prints 42!
另一方面,
Clone()
通常用于指示对象本身的副本,这意味着
test
newTest2
将指向不同的对象,因此不会发生上述情况


请注意,如果测试是一个
结构(值类型),那么直接赋值实际上是对象的完整(浅层)副本(按值)。

新测试实际上指向内存中与测试相同的对象,因此修改新测试会更改测试。newTest2实际上是test的副本。

赋值只复制引用,而不复制对象本身


如果您的类实现了,那么可以编写它来执行深度复制操作,即返回新分配的相同类型的对象,其字段是原始对象的副本。一个有趣的问题是,当字段是引用类型时,该怎么做:复制引用,还是深度复制引用对象?例如,仅复制引用(这称为浅层复制),但如果选择实施,则可以自行决定

要理解区别,首先必须理解对象引用是什么。由于术语“reference”用于指代许多不同的概念,因此我喜欢术语“objectid”。以汽车为例,对象ID是一张写有汽车VIN的纸条。如果你递给油漆店一张写有“VIN ZX357”的纸,并要求油漆店将其漆成蓝色,那么油漆店不会将纸条漆成蓝色,而是会找到带有该VIN编号的汽车并将其漆成蓝色

如果一个变量
Wuzzle
的类型为
Car
(参考类型)恰好保持“VIN ZX357”,另一个变量
Fuzzle
,并且一个变量说
Fuzzle=Wuzzle
,那么
Fuzzle
将像
Wuzzle
保持“VIN ZX357”。还有一辆车。其中一辆车只有两张纸条,两张纸条上都有相同的VIN,因此指的是同一辆车。类似于
Wuzzle.Color=Purple
的语句将导致VIN为ZX357的汽车漆成紫色。检查
Fuzzle.Color
的请求将查看ZX357汽车并报告它是紫色的

如果不是说
Fuzzle=Wuzzle
,而是说
Fuzzle=(Car)(Wuzzle.Clone())
,其效果将是创建一辆与VIN ZX357类似的新车,只是它会有一个不同的VIN编号(例如QL793),并且
Fuzzle
会保留新的VIN,而不是3941QXY5)。然后说
Wuzzle.Color=Orange
会将汽车3941QXY5漆成橙色,但不会影响汽车QL793

接口类型的变量与任何其他引用类型一样处理。人们可以用
IColorizable
代替
Car
,其行为将完全相同

需要注意的是,
ICloneable
不是一个很好的接口;更好的接口是
ICloneable
,它返回类型为
T
的对象。此接口有两大优点:

  • 使用
    ICloneable
    ,有必要将返回类型转换为所需的对象类型。这有点难看<代码>可克隆
  • 消除了此要求
  • 使用
    ICloneable
    ,对于对象中的哪些对象引用应按原样复制到克隆,以及哪些对象引用本身应被克隆,可能存在一些模糊性。这种模糊性并不像有些人所说的那么糟糕,但是通用的
    ICloneable
    可以让它更清晰一些。例如,如果一个人有一个对象
    CloneableSortedList
    ,那么调用
    ICloneAbleWhat可以看出Car c=new Car和d=(Car)(c.Clone())之间的区别@Charlie:克隆默认值实例可能会产生一个与默认构造函数返回的结果非常相似的实例。你还想要别的吗?