C# System.Array.CopyTo() 和 System.Array.Clone() 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/198496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:40:45  来源:igfitidea点击:

Difference between the System.Array.CopyTo() and System.Array.Clone()

c#.netarrays.net-2.0

提问by Mister Dev

What's the difference between the System.Array.CopyTo()and System.Array.Clone()?

有什么之间的区别System.Array.CopyTo()System.Array.Clone()

采纳答案by Patrick Desjardins

The Clone()method returns a new array (a shallow copy) object containing all the elements in the original array. The CopyTo()method copies the elements into another existing array. Both perform a shallow copy. A shallow copy means the contents (each array element) contains references to the same object as the elements in the original array. A deep copy (which neither of these methods performs) would create a new instance of each element's object, resulting in a different, yet identical object.

克隆()方法返回一个新的数组包含原始阵列中的所有元件(浅表副本)对象。所述CopyTo从()方法复制的元素到另一个现有阵列。两者都执行浅拷贝。浅拷贝意味着内容(每个数组元素)包含对与原始数组中元素相同的对象的引用。深度复制(这两种方法都不会执行)会为每个元素的对象创建一个新实例,从而产生一个不同但相同的对象。

So the difference are :

所以区别是:

1- CopyTo require to have a destination array when Clone return a new array.
2- CopyTo let you specify an index (if required) to the destination array.
编辑:

Remove the wrong example.

删除错误示例。

回答by FlySwat

Both perform shallow copies as @PatrickDesjardins said (despite the many misled souls who think that CopyTodoes a deep copy).

正如@PatrickDesjardins 所说,两者都执行浅拷贝(尽管许多被误导的灵魂认为这CopyTo是深拷贝)。

However, CopyToallows you to copy one array to a specified index in the destination array, giving it significantly more flexibility.

但是,CopyTo允许您将一个数组复制到目标数组中的指定索引,从而使其具有更大的灵活性。

回答by Michael Burr

One other difference not mentioned so far is that

到目前为止没有提到的另一个区别是

  • with Clone()the destination array need not exist yet since a new one is created from scratch.
  • with CopyTo()not only does the destination array need to already exist, it needs to be large enough to hold all the elements in the source array from the index you specify as the destination.
  • Clone()目标阵列需要,因为一个新的从头开始创建还不存在。
  • CopyTo()不仅目标数组必须已经存在,它需要足够大,以容纳从您指定为目标的索引源阵列中的所有元素。

回答by GenZiy

object[] myarray = new object[] { "one", 2, "three", 4, "really big number", 2324573984927361 };

//create shallow copy by CopyTo
//You have to instantiate your new array first
object[] myarray2 = new object[myarray.Length];
//but then you can specify how many members of original array you would like to copy 
myarray.CopyTo(myarray2, 0);

//create shallow copy by Clone
object[] myarray1;
//here you don't need to instantiate array, 
//but all elements of the original array will be copied
myarray1 = myarray.Clone() as object[];

//if not sure that we create a shalow copy lets test it
myarray[0] = 0;
Console.WriteLine(myarray[0]);// print 0
Console.WriteLine(myarray1[0]);//print "one"
Console.WriteLine(myarray2[0]);//print "one"

the source

来源

回答by GenZiy

Clone()is used to copy only structure of data/array it doesn't copy the actual data.

Clone()用于仅复制数据/数组的结构,它不复制实际数据。

CopyTo()copies the structure as well as actual data.

CopyTo()复制结构以及实际数据。

回答by Prasad

Both CopyTo() and Clone() make shallow copy. Clone() method makes a clone of the original array. It returns an exact length array.

CopyTo() 和 Clone() 都是浅拷贝。Clone() 方法克隆原始数组。它返回一个精确长度的数组。

On the other hand, CopyTo() copies the elements from the original array to the destination array starting at the specified destination array index. Note that, this adds elements to an already existing array.

另一方面, CopyTo() 从指定的目标数组索引开始将元素从原始数组复制到目标数组。请注意,这会将元素添加到已存在的数组中。

The following code will contradict the postings saying that CopyTo() makes a deep copy:

以下代码将与说 CopyTo() 进行深层复制的帖子相矛盾:

public class Test
{
public string s;
}

// Write Main() method and within it call test()

private void test()
{
Test[] array = new Test[1];
array[0] = new Test();
array[0].s = "ORIGINAL";

Test[] copy = new Test[1];
array.CopyTo(copy, 0);

// Next line displays "ORIGINAL"
MessageBox.Show("array[0].s = " + array[0].s);
copy[0].s = "CHANGED";

// Next line displays "CHANGED", showing that
// changing the copy also changes the original.
MessageBox.Show("array[0].s = " + array[0].s);
}

Let me explain it a bit. If the elements of the array are of reference types, then the copy (both for Clone() and CopyTo()) will be made upto the first(top) level. But the lower level doesn't get copied. If we need copy of lower level also, we have to do it explicitly. That's why after Cloning or Copying of reference type elements, each element in the Cloned or Copied array refers to the same memory location as referred by the corresponding element in the original array. This clearly indicates that no separate instance is created for lower level. And if it were so then changing the value of any element in the Copied or Cloned array would not have effect in the corresponding element of the original array.

让我解释一下。如果数组的元素是引用类型,那么副本(Clone() 和 CopyTo())将被制作到第一(顶级)级别。但是较低的级别不会被复制。如果我们还需要较低级别的副本,我们必须明确地这样做。这就是为什么在克隆或复制引用类型元素后,克隆或复制数组中的每个元素都引用与原始数组中相应元素引用的相同内存位置。这清楚地表明没有为较低级别创建单独的实例。如果是这样,那么更改复制或克隆数组中任何元素的值将不会对原始数组的相应元素产生影响。

I think that my explanation is exhaustive but I found no other way to make it understandable.

我认为我的解释是详尽无遗的,但我没有找到其他方法可以理解。

回答by Mohammad Ahmed

The Clone()method don't give reference to the target instance just give you a copy. the CopyTo()method copies the elements into an existing instance.

Clone()方法不提供对目标实例的引用,只是给你一个副本。该CopyTo()方法将元素复制到现有实例中。

Both don't give the reference of the target instance and as many members says they give shallow copy (illusion copy) without reference this is the key.

两者都没有给出目标实例的引用,正如许多成员所说,他们给出了没有引用的浅拷贝(幻觉拷贝),这是关键。

回答by Jo?o Angelo

As stated in many other answers both methods perform shallow copiesof the array. However there are differences and recommendations that have not been addressed yet and that are highlighted in the following lists.

正如许多其他答案中所述,这两种方法都执行数组的浅拷贝。但是,存在尚未解决的差异和建议,并在以下列表中突出显示。

Characteristics of System.Array.Clone:

特点System.Array.Clone

  • Tests, using .NET 4.0, show that it is slower than CopyToprobably because it uses Object.MemberwiseClone;
  • Requires casting the resultto the appropriate type;
  • The resulting array has the same length as the source.
  • 使用 .NET 4.0 的测试表明它CopyTo可能的要慢,因为它使用Object.MemberwiseClone;
  • 需要将结果转换为适当的类型;
  • 结果数组与源具有相同的长度。

Characteristics of System.Array.CopyTo:

特点System.Array.CopyTo

  • Is faster than Clonewhen copying to array of same type;
  • It calls into Array.Copyinheriting is capabilities, being the most useful ones:
    • Can box value type elements into reference type elements, for example, copying an int[]array into an object[];
    • Can unbox reference type elements into value type elements, for example, copying a object[]array of boxed intinto an int[];
    • Can perform widening conversions on value types, for example, copying a int[]into a long[].
    • Can downcast elements, for example, copying a Stream[]array into a MemoryStream[](if any element in source array is not convertible to MemoryStreaman exception is thrown).
  • Allows to copy the source to a target array that has a length greater than the source.
  • Clone复制到相同类型的数组时更快
  • 它调用Array.Copy继承 is capabilities,是最有用的:
    • 可以将值类型元素装箱成引用类型元素,例如,将int[]数组复制到object[];
    • 可以将引用类型元素拆箱为值类型元素,例如,将object[]装箱的数组复制intint[];
    • 可以对值类型执行扩展转换,例如,将 a 复制int[]到 a 中long[]
    • 可以向下转换元素,例如,将Stream[]数组复制到 a MemoryStream[](如果源数组中的任何元素不可转换为MemoryStream异常则抛出)。
  • 允许将源复制到长度大于源的目标数组。

Also note, these methods are made available to support ICloneableand ICollection, so if you are dealing with variables of array types you should not use Cloneor CopyToand instead use Array.Copyor Array.ConstrainedCopy. The constrained copy assures that if the copy operation cannot complete successful then the target array state is not corrupted.

另请注意,这些方法可用于支持ICloneableand ICollection,因此如果您正在处理数组类型的变量,则不应使用CloneorCopyTo而应使用Array.Copyor Array.ConstrainedCopy。受约束的复制确保如果复制操作无法成功完成,则目标阵列状态不会损坏。

回答by Stranger

The answers are confusing to me. When you say shallow copy, this means that they are still pointing to the same address. Which means, changing either one will change another as well.

答案让我很困惑。当你说浅拷贝时,这意味着它们仍然指向同一个地址。这意味着,改变任何一个也会改变另一个。

So if I have A = [1,2,3,4] and I clone it and get B = [1,2,3,4]. Now, if I change B[0] = 9. This means that A will now be A = [9,2,3,4]. Is that correct?

所以如果我有 A = [1,2,3,4] 并且我克隆它并得到 B = [1,2,3,4]。现在,如果我更改 B[0] = 9。这意味着 A 现在将是 A = [9,2,3,4]。那是对的吗?

回答by inbaly

Please note: There is a difference between using String[] to StringBuilder[].

请注意:使用 String[] 和 StringBuilder[] 是有区别的。

In String - if you change the String, the other arrays we have copied (by CopyTo or Clone) that points to the same string will not change, but the original String array will point to a new String, however, if we use a StringBuilder in an array, the String pointer will not change, therefore, it will affect all the copies we have made for this array. For instance:

在字符串中 - 如果更改字符串,我们复制(通过 CopyTo 或 Clone)指向同一字符串的其他数组将不会更改,但原始字符串数组将指向一个新字符串,但是,如果我们使用 StringBuilder在数组中,String 指针不会改变,因此,它会影响我们为此数组所做的所有副本。例如:

public void test()
{
    StringBuilder[] sArrOr = new StringBuilder[1];
    sArrOr[0] = new StringBuilder();
    sArrOr[0].Append("hello");
    StringBuilder[] sArrClone = (StringBuilder[])sArrOr.Clone();
    StringBuilder[] sArrCopyTo = new StringBuilder[1];
    sArrOr.CopyTo(sArrCopyTo,0);
    sArrOr[0].Append(" world");

    Console.WriteLine(sArrOr[0] + " " + sArrClone[0] + " " + sArrCopyTo[0]);
    //Outputs: hello world hello world hello world

    //Same result in int[] as using String[]
    int[] iArrOr = new int[2];
    iArrOr[0] = 0;
    iArrOr[1] = 1;
    int[] iArrCopyTo = new int[2];
    iArrOr.CopyTo(iArrCopyTo,0);
    int[] iArrClone = (int[])iArrOr.Clone();
    iArrOr[0]++;
    Console.WriteLine(iArrOr[0] + " " + iArrClone[0] + " " + iArrCopyTo[0]);
   // Output: 1 0 0
}