System.Array.CopyTo()
和之间有什么区别System.Array.Clone()
?
System.Array.CopyTo()
和之间有什么区别System.Array.Clone()
?
Answers:
该克隆()方法返回一个新的数组包含原始阵列中的所有元件(浅表副本)对象。所述CopyTo从()方法复制的元素到另一个现有阵列。两者都执行浅表复制。浅表副本意味着内容(每个数组元素)包含对与原始数组中的元素相同的对象的引用。深拷贝(这些方法都不执行)将创建每个元素对象的新实例,从而产生一个不同但相同的对象。
所以区别是:
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.
编辑:
删除错误的示例。
numbersCopy
只是对分配给的数组的另一个引用numbers
。这是不一样的使用CopyTo()
方法。如果使用CopyTo()
,您将获得与Clone()
示例相同的结果。另外,这是C#-System.out.println
应该是Console.WriteLine
。
ToArray()
方法提供了一种简单得多的(和类型的浅克隆阵列反正的)的方式。由于数组是IENumerable<T>
它的作品。
如许多其他答案所述,这两种方法都执行数组的浅表复制。但是,存在一些差异和建议尚未解决,并在以下列表中突出显示。
CopyTo
可能是因为它使用Object.MemberwiseClone
;Clone
复制到相同类型的数组时要快;Array.Copy
继承为功能,是最有用的功能:
int[]
数组复制到object[]
;中。object[]
装箱的数组复制int
到int[]
;int[]
到long[]
。Stream[]
数组复制到中MemoryStream[]
(如果MemoryStream
抛出了源数组中的任何元素都不能转换为异常)。还要注意,这些方法可用于支持ICloneable
和ICollection
,因此,如果要处理数组类型的变量,则不应使用Clone
或CopyTo
,而应使用Array.Copy
或Array.ConstrainedCopy
。受限复制可确保如果复制操作无法成功完成,则目标阵列状态不会损坏。
.ToArray()
方法。它仍然会进行复制,并且可以在任何IEnumerable<>
数组(包括数组)上执行。而且.Clone()
,它与键入不同,因此不需要强制转换。
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"
CopyTo()和Clone()都进行浅拷贝。Clone()方法复制原始数组。它返回一个精确的长度数组。
另一方面,CopyTo()从指定的目标数组索引开始,将元素从原始数组复制到目标数组。请注意,这会将元素添加到现有数组中。
下面的代码将与帖子说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);
}
让我解释一下。如果数组的元素是引用类型,则副本(用于Clone()和CopyTo())将被复制到第一(顶层)级别。但是较低级别不会被复制。如果我们还需要较低级别的副本,则必须明确地执行它。这就是为什么在克隆或复制引用类型元素之后,克隆或复制数组中的每个元素都引用与原始数组中相应元素所引用的相同的内存位置。这清楚地表明没有为较低级别创建单独的实例。如果是这样,那么更改“复制”或“克隆”数组中任何元素的值将不会对原始数组的相应元素产生影响。
我认为我的解释是详尽无遗的,但我发现没有其他方法可以使它易于理解。
Array.Clone()
传递数组时,将执行技术上较深的复制 int
或string给方法作为引用。
例如
int[] numbers = new int[] { -11, 12, -42, 0, 1, 90, 68, 6, -9 };
SortByAscending(numbers); // Sort the array in ascending order by clone the numbers array to local new array.
SortByDescending(numbers); // Same as Ascending order Clone
即使这些方法对数字数组进行了排序,但它不会影响传递给排序方法的实际引用。即,数字数组将以相同的未排序初始格式排在第1行。
注意:克隆应在排序方法中完成。
该Clone()
方法不提供对目标实例的引用,只是给您一个副本。的CopyTo()
方法将元素复制到现有实例中。
两者都没有给出目标实例的引用,并且许多成员说他们给出了没有引用的浅表副本(幻觉副本),这是关键。
答案使我感到困惑。当您说浅拷贝时,这意味着它们仍指向相同的地址。这意味着,改变任何一个都会改变另一个。
因此,如果我有A = [1,2,3,4]并克隆它并得到B = [1,2,3,4]。现在,如果我更改B [0] =9。这意味着A现在将是A = [9,2,3,4]。那是对的吗?
两者都是浅表副本。CopyTo方法不是深层副本。 检查以下代码:
public class TestClass1
{
public string a = "test1";
}
public static void ArrayCopyClone()
{
TestClass1 tc1 = new TestClass1();
TestClass1 tc2 = new TestClass1();
TestClass1[] arrtest1 = { tc1, tc2 };
TestClass1[] arrtest2 = new TestClass1[arrtest1.Length];
TestClass1[] arrtest3 = new TestClass1[arrtest1.Length];
arrtest1.CopyTo(arrtest2, 0);
arrtest3 = arrtest1.Clone() as TestClass1[];
Console.WriteLine(arrtest1[0].a);
Console.WriteLine(arrtest2[0].a);
Console.WriteLine(arrtest3[0].a);
arrtest1[0].a = "new";
Console.WriteLine(arrtest1[0].a);
Console.WriteLine(arrtest2[0].a);
Console.WriteLine(arrtest3[0].a);
}
/* Output is
test1
test1
test1
new
new
new */
Array.Clone不需要目标/目标阵列调用函数时,而可用Array.CopyTo需要一个目标数组和索引。
请注意:使用String []与StringBuilder []之间有区别。
在String中-如果更改String,则我们复制(通过CopyTo或Clone)复制的指向同一字符串的其他数组不会更改,但是原始String数组将指向新的String,但是,如果我们使用StringBuilder在数组中,字符串指针不会改变,因此,它将影响我们为此数组创建的所有副本。例如:
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
}
CopyTo
vs无关Clone
。它只是参考语义与值语义。int是一种值类型,因此您每次都会获得一个新副本。StringBuilder具有引用语义,因此您要对同一副本进行操作。