克隆方法和直接将实例分配给另一个实例有什么区别

发布于 2024-12-21 07:41:21 字数 188 浏览 3 评论 0 原文

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

Test test = new Test();
Test newTest = test;
Test newTest2 = test.Clone();

newTest 和 newTest2 之间有什么区别? 有人可以帮忙吗? 提前致谢!

I want to know, if I have a class named Test, what's the difference below

Test test = new Test();
Test newTest = test;
Test newTest2 = test.Clone();

What's the different between newTest and newTest2?
Anyone can help?
Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

樱桃奶球 2024-12-28 07:41:21

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

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

Test test = new Test();
test.Foo = 24;
Test newTest = test;
newTest.Foo = 42;
Console.WriteLine(test.Foo); // Prints 42!

Clone(),另一方面,通常用于指示对象本身的副本,这意味着 test和 newTest2 会指向不同的对象,因此上述情况不会发生。

请注意,如果 test 是struct(值类型),则直接赋值实际上是对象按值的完整(浅)副本。

When you assign the instance, if Test is a class, you're actually copying the reference, but test and newTest will both point to the same instance in memory.

This means that both variables point to the same object:

Test test = new Test();
test.Foo = 24;
Test newTest = test;
newTest.Foo = 42;
Console.WriteLine(test.Foo); // Prints 42!

Clone(), on the other hand, typically is used to indicate a copy of the object itself, which means that test and newTest2 would point to different objects, so the above wouldn't happen.

Note that, if test is a struct (value type), then a direct assignment is effectively a full (shallow) copy of the object, by value.

皇甫轩 2024-12-28 07:41:21

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

如果有一个 Car 类型(引用类型)的变量 Wuzzle 恰好包含“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 类型的对象。该接口有两大优点:

  1. 对于ICloneable,有必要将返回类型强制转换为所需的对象类型。这有点难看。 ICloneable 消除了这一要求。
  2. 使用ICloneable,对于对象中的哪些对象引用应按原样复制到克隆,以及哪些对象引用本身应被克隆,可能存在一些模糊性。这种歧义并不像某些人所说的那么糟糕,但通用的 ICloneable 可以让它变得更清晰一些。例如,如果有一个对象 CloneableSortedList,则在该列表上调用 ICloneable.Clone() 应返回一个新的 CloneableSortedList 其中包含与原始类型 T 相同的引用。相比之下,如果有一个 CloneableSortedUserList,调用 ICloneable 应返回一个新的 CloneableSortedUserList,它将考虑用户的属性,而不是用户对象引用作为值(如果它们是可变的,则复制它们)。

To understand the distinction, one must first understand what an object reference is. Since the term "reference" is used to refer to a number of different concepts, I like the term "Object ID". To use an automotive analogy, an object ID is a slip of paper with a car's VIN on it. If you hand the paint shop a piece of paper with "VIN ZX357" written on it and ask the shop to paint it blue, the shop won't paint the slip of paper blue, but rather they will find the car with that VIN number and paint that car blue.

If one has a variable Wuzzle of type Car (which is reference type) that happens to hold "VIN ZX357", and another variable Fuzzle, and one says Fuzzle = Wuzzle, then Fuzzle will--like Wuzzle hold "VIN ZX357". There will still be one car. One will just have two slips of paper, both of which hold the same VIN, and thus refer to the same car. A statement like Wuzzle.Color=Purple will cause the car whose VIN is ZX357to be painted purple. A request to examine Fuzzle.Color will look at car ZX357and report that it's purple.

If instead of saying Fuzzle = Wuzzle, one had said Fuzzle = (Car)(Wuzzle.Clone()), the effect would be to create a new car that was just like VIN ZX357, except that it would have a different VIN number (e.g. QL793) and Fuzzle would hold the new VIN, not 3941QXY5). Saying Wuzzle.Color = Orange would then paint car 3941QXY5 orange, but it wouldn't affect car QL793.

Variables of interface type are treated just like any other reference type. One could substitute IColorizable for Car and the behavior would be exactly the same.

It's important to note that ICloneable isn't a very good interface; a much better interface is ICloneable<T> which returns an object of type T. There are two big advantages to this interface:

  1. With ICloneable, it's necessary to typecast the return type to the type of object one wants. This is a bit ugly. ICloneable<T> eliminates this requirement.
  2. With ICloneable, there can be some ambiguity as to which object references within an object should be copied as-is to the clone, and which ones should themselves be cloned. The ambiguity isn't nearly as bad as some people make it out to be, but the generic ICloneable<T> can make it a little clearer. For example, if one has an object CloneableSortedList<T>, then calling ICloneable<CloneableSortedList<T>.Clone() on that list should return a new CloneableSortedList which contains the same references to type T as the original one did. By contrast, if one has a CloneableSortedUserList, calling ICloneable<CloneableSortedUserList> should return a new CloneableSortedUserList which will regard the users' attributes, rather than the user object references, as values (thus copying them if they are mutable).
勿挽旧人 2024-12-28 07:41:21

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

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

Assignment copies only the reference, not the object itself.

If your class implements IClonable.Clone, it can be written to perform a deep copy operation, that is, to return a newly allocated object of the same type, the fields of which are copies of the original. It's an interesting question what to do when a field is a reference type: copy the reference, or deep-copy the referenced object? For example, Object.MemberwiseClone copies only the reference (this is called a shallow copy), but if you choose to implement IClonable.Clone, then you can decide this yourself.

萌︼了一个春 2024-12-28 07:41:21
Test newTest = test;

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

Test newTest2 = test.Clone();

假设 Clone() 返回一个 new 实例并执行深层复制(这实际上取决于您的实现),newTest2 指的是完全单独的对象,test 中的任何更改都不会影响它。

Test newTest = test;

Since Test is a reference type (class), newTest now references the same object as test. If you change the object test references, that will be reflected in newTest since they both reference to the same object.

Test newTest2 = test.Clone();

Assuming Clone() is returning a new instance and does a deep copy (it truly depends on your implementation) , newTest2 is referring to a completely separate object, any changes in test won't affect it.

记忆之渊 2024-12-28 07:41:21

new test 实际上与 test 指向内存中的同一个对象,因此修改 newTest 会改变 test。 newTest2实际上是test的副本。

New test actually points to the same object in memory as test, so modifying newTest changes test. newTest2 is actually a copy of test.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文