В чем разница между System.Array.CopyTo()
и System.Array.Clone()
?
Разница между System.Array.CopyTo() и System.Array.Clone()
Ответ 1
Метод Clone() возвращает объект с новым массивом (мелкой копией), содержащий все элементы в оригинальный массив. Метод 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.
Редактировать:
Удалите неправильный пример.
Ответ 2
Еще одно отличие, не упомянутое до сих пор, заключается в том, что
- с
Clone()
целевой массив еще не существует, поскольку новый создается с нуля. - с
CopyTo()
должен существовать не только целевой массив, он должен быть достаточно большим, чтобы содержать все элементы в исходном массиве из указателя, который вы указываете в качестве адресата.
Ответ 3
Оба выполняют мелкие копии, как сказал @PatrickDesjardins (несмотря на множество заблужденных душ, которые считают, что CopyTo
делает глубокую копию).
Однако CopyTo
позволяет копировать один массив в указанный индекс в целевом массиве, что дает ему значительно большую гибкость.
Ответ 4
Как указано во многих других ответах, оба метода выполняют поверхностные копии массива. Однако есть различия и рекомендации, которые еще не были учтены и выделены в следующих списках.
Характеристики System.Array.Clone
:
- Тесты, использующие .NET 4.0, показывают, что он медленнее, чем
CopyTo
вероятно, потому что он используетObject.MemberwiseClone
; - Требуется приведение результата к соответствующему типу;
- Полученный массив имеет ту же длину, что и исходный.
Характеристики System.Array.CopyTo
:
- Быстрее, чем
Clone
при копировании в массив того же типа; - Он вызывает
Array.Copy
наследование - это возможности, наиболее полезные из них:- Может вставлять элементы типа значения в элементы ссылочного типа, например, копируя массив
int[]
вobject[]
; - Может распаковывать элементы ссылочного типа в элементы типа значения, например, копируя массив
object[]
из упакованногоint
вint[]
; - Может выполнять расширенные преобразования для типов значений, например, копируя
int[]
вlong[]
. - Может понижать элементы, например, копируя массив
Stream[]
вMemoryStream[]
(если какой-либо элемент в исходном массиве не конвертируется вMemoryStream
генерируется исключение).
- Может вставлять элементы типа значения в элементы ссылочного типа, например, копируя массив
- Позволяет скопировать источник в целевой массив, длина которого больше, чем у источника.
Также обратите внимание, что эти методы доступны для поддержки ICloneable
и ICollection
, поэтому, если вы имеете дело с переменными типов массивов, вам не следует использовать Clone
или CopyTo
и вместо этого использовать Array.Copy
или Array.ConstrainedCopy
. Ограниченная копия гарантирует, что если операция копирования не может завершиться успешно, то состояние целевого массива не будет повреждено.
Ответ 5
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"
Ответ 6
Оба 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()) будет выполнена до первого (верхнего) уровня. Но нижний уровень не копируется. Если нам нужна копия более низкого уровня, мы должны сделать это явно. Поэтому после клонирования или копирования элементов ссылочного типа каждый элемент в клонированном или скопированном массиве относится к той же ячейке памяти, что и соответствующий элемент в исходном массиве. Это ясно указывает на то, что для более низкого уровня не создается отдельный экземпляр. И если бы это было так, то изменение значения любого элемента в скопированном или клонированном массиве не имело бы эффекта в соответствующем элементе исходного массива.
Я думаю, что мое объяснение является исчерпывающим, но я не нашел другого способа сделать его понятным.
Ответ 7
Метод Clone()
не дает ссылки на целевой экземпляр, просто дайте вам копию.
метод CopyTo()
копирует элементы в существующий экземпляр.
Оба не дают ссылки на целевой экземпляр, и многие члены говорят, что они дают мелкую копию (иллюстрационную копию) без ссылки, это ключ.
Ответ 8
Ответы меня смущают. Когда вы произносите неглубокую копию, это означает, что они все еще указывают на тот же адрес. Это означает, что изменение одного из них также изменит и другое.
Итак, если у меня есть A = [1,2,3,4], и я клонирую его и получаю B = [1,2,3,4]. Теперь, если я изменю B [0] = 9. Это означает, что теперь A будет A = [9,2,3,4]. Это правильно?
Ответ 9
Оба - мелкие копии. Метод 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 */
Ответ 10
Array.CopyTo не требует наличия целевого/целевого массива при вызове функции, тогда как Array.CopyTo требует целевого массива и индекса.
Ответ 11
Clone()
используется для копирования только структуры данных/массива, которая не копирует фактические данные.
CopyTo()
копирует структуру, а также фактические данные.
Ответ 12
Обратите внимание: существует разница между использованием String [] в StringBuilder [].
В String - если вы измените String, другие массивы, которые мы скопировали (CopyTo или Clone), которые указывают на одну и ту же строку, не будут изменены, но исходный массив String укажет на новую строку, однако, если мы используйте 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
}