【问题标题】:Strange behavior of Array.Clone()Array.Clone() 的奇怪行为
【发布时间】:2011-02-23 13:25:08
【问题描述】:

我有一个像下面这样的静态数组

static byte[] myArray = {0x01,0x02};

我读到Array.clone does shallow copy。然后我执行下面的代码。

byte[] myArray2 = myArray.Clone() as byte[];
myArray2[0] = 0x05;

但是现在每个 myArray2[0] 和 myArray[0] 都包含不同的值。所以我认为 Array.Clone() 正在执行深层复制。你能解释一下为什么吗?

【问题讨论】:

  • 嗨,浅拷贝或深拷贝在 byte 或 int 等简单值类型的上下文中没有意义。由于数组包含值而不是引用,因此一旦克隆它并更改其中任何一个中的值,此类更改不会传播到另一个数组。

标签: c#


【解决方案1】:

byte 是原始类型,而不是引用。因此在这种情况下,浅拷贝和深拷贝没有区别。

尝试使用可变对象类型的数组,你会发现不同。

更新

但是 byte[] 是引用类型对吗?

一个原始类型的数组最有可能由一个连续的内存块表示,物理上(按值)包含元素。而对象类型的数组是一个连续的内存块,只包含对实际元素(或nulls)的引用。因此,当您复制数组时,在第一种情况下,您会得到一个包含原始元素的 副本 的新数组。所以在那之后,修改其中一个数组中的元素不会改变另一个数组的内容。而在第二种情况下,您将获得一个包含原始 references 副本的新数组,仍然指向原始数组元素引用的相同对象。因此,如果您修改任一数组中的任何元素,则更改也将在另一个数组中可见。

【讨论】:

  • 尝试使用可变引用类型,即:Person[],您会看到。
  • @Vaysage:克隆是复制数组的内容,而不是数组本身。数组的内容是值类型。见msdn.microsoft.com/en-us/library/system.array.clone.aspx
  • @Vaysage 但是 Clone 对数组的元素进行操作,在这种情况下它们不是引用类型。
【解决方案2】:

浅拷贝意味着它复制立即值。如果这些值是指针(引用类型,如 C# 中的对象),则指针会被复制,而它们指向的值(对象的状态)不会被复制。

如果直接值是原始值(即:值本身驻留在数组中,它不是引用),那么这些值会被复制。因此,行为完全符合预期。

如果您想查看您的情况的不同之处,请定义一个 Objects 数组。

【讨论】:

  • Byte 不是盒装字节。这是 C#,不是 Java。
  • @LukeH 是的。来回切换的危险。
【解决方案3】:

试试这个:

public class Person
{
    public string Name { get; set; }
}

Person person = new Person { Name = "Vaysage" };

Person[] persons1 = new Person[] { person  };

Person[] persons2 = (Person[])persons1.Clone();

persons2[0].Name = ".NET Junkie";

Assert.AreEqual(persons1[0].Name, ".NET Junkie");

数组被浅拷贝。这意味着只复制对Person 对象的引用,而不是整个对象。两个数组都引用同一个人对象,因此第一个数组中的人名也发生了变化。

【讨论】:

  • 谢谢。现在我明白Array.Clone 对数组成员有效。以前我相信它适用于数组,这就是我问这个问题的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 2015-07-20
  • 2010-10-03
  • 2021-07-12
  • 2013-10-04
  • 2019-01-23
相关资源
最近更新 更多