Разница между системой.Матрица.CopyTo() и система.Матрица.Клон()


в чем разница между System.Array.CopyTo() и System.Array.Clone()?

11 65

11 ответов:

на 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.
Редактировать:

удалить неправильный пример.

еще одно отличие, не упомянутое до сих пор, заключается в том, что

  • С Clone() целевой массив еще не должен существовать, так как новый создается с нуля.
  • С CopyTo() мало того, что целевой массив должен уже существовать, он должен быть достаточно большим, чтобы содержать все элементы в исходном массиве из индекса, указанного в качестве целевого.

оба выполняют мелкие копии, как сказал @PatrickDesjardins (несмотря на многие обманутые души, которые думают, что CopyTo делает глубокую копию).

однако, CopyTo позволяет скопировать один массив в указанный индекс в целевом массиве, что дает ему значительно большую гибкость.

как указано во многих других ответах, оба метода выполняют неглубокое копии массива. Однако существуют различия и рекомендации, которые еще не были рассмотрены и которые выделены в следующих списках.

характеристики System.Array.Clone:

  • тесты, использующие .NET 4.0, показывают, что это медленнее, чем CopyTo наверное, потому, что он использует Object.MemberwiseClone;
  • требует приведения результата к соответствующему типу;
  • результирующий массив имеет ту же длину, что и исходный.

характеристики System.Array.CopyTo:

  • быстрее Clone при копировании в массив такого же типа;
  • он звонит в Array.Copy наследование-это возможности, будучи наиболее полезные:
    • можно поместить элементы типа значения в элементы ссылочного типа, например, скопировав int[] массив в object[];
    • можно распаковать элементы ссылочного типа В тип параметра, например, для копирования object[] массив в штучной упаковке int на int[];
    • может выполнять расширяющие преобразования для типов значений, например, копирование a int[] на long[].
    • можно понизить элементы, например, копирование a Stream[] массив в MemoryStream[] (если какой-либо элемент в исходном массиве не преобразуется в MemoryStream исключение).
  • позволяет скопировать источник в целевой массив, длина которого больше длины источника.

Также обратите внимание, что эти методы доступны для поддержки ICloneable и ICollection, так что если вы имеете дело с переменными типа массив, вы не должны использовать Clone или CopyTo и вместо использования Array.Copy или Array.ConstrainedCopy. Ограниченная копия гарантирует, что если операция копирования не может завершиться успешно, то состояние целевого массива не повреждено.

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 ()) будет составлена до первого (верхнего) уровня. Но нижний уровень не копируется. Если нам также нужна копия более низкого уровня, мы должны сделать это явно. Вот почему после клонирования или копирования элементов ссылочного типа каждый элемент в клонированном или скопированном массиве ссылается на ту же ячейку памяти, на которую ссылается соответствующий элемент в исходный массив. Это ясно указывает на то, что для более низкого уровня не создается отдельный экземпляр. И если бы это было так, то изменение значения любого элемента в скопированном или клонированном массиве не имело бы эффекта в соответствующем элементе исходного массива.

Я думаю, что мое объяснение является исчерпывающим, но я не нашел другого способа, чтобы сделать ее понятной.

The 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 */

Clone() используется для копирования только структуры данных / массива он не копирует фактические данные.

CopyTo() копирует структуру, а также фактические данные.

обратите внимание: существует разница между использованием String[] для StringBuilder[].

в строке - если вы измените строку, в других массивах, то есть копируется (копирование, чтобы купить или Клон), который указывает на ту же строку не изменится, но исходный массив строк будет указывать на новую строку, однако, если использовать 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
}