Diferencia entre el Sistema.Matriz.CopyTo () y Sistema.Matriz.Clon()


¿Cuál es la diferencia entre System.Array.CopyTo() y System.Array.Clone()?

Author: Amar Palsapure, 2008-10-13

11 answers

El Clon() method devuelve un objeto nuevo array (una copia superficial) que contiene todos los elementos del array original. Las CopyTo() method copia los elementos en otra matriz existente. Ambos realizan una copia superficial. Una copia superficial significa que el contenido (cada elemento del array) contiene referencias al mismo objeto que los elementos del array original. Una copia profunda (que ninguno de estos métodos realiza) crearía una nueva instancia de cada elemento objeto, resultando en un objeto diferente, pero idéntico.

Así que la diferencia es:

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.
Editar:

Elimine el ejemplo equivocado.

 38
Author: Patrick Desjardins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-14 19:50:16

Otra diferencia no mencionada hasta ahora es que

  • con Clone() la matriz de destino no necesita existir todavía ya que se crea una nueva desde cero.
  • con CopyTo() no solo es necesario que la matriz de destino ya exista, sino que debe ser lo suficientemente grande como para contener todos los elementos de la matriz de origen del índice que especifique como destino.
 21
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-13 18:45:50

Ambos realizan copias superficiales como dijo @PatrickDesjardins (a pesar de las muchas almas engañadas que piensan que CopyTo hace una copia profunda).

Sin embargo, CopyTo le permite copiar una matriz a un índice especificado en la matriz de destino, dándole significativamente más flexibilidad.

 19
Author: FlySwat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-21 10:29:08

Como se indica en muchas otras respuestas, ambos métodos realizan copias superficiales del array. Sin embargo, hay diferencias y recomendaciones que aún no se han abordado y que se destacan en las siguientes listas.

Características de System.Array.Clone:

  • Las pruebas, usando. NET 4.0, muestran que es más lento que CopyTo probablemente porque utiliza Object.MemberwiseClone;
  • Requiere lanzar el resultado al apropiado tipo;
  • El array resultante tiene la misma longitud que la fuente.

Características de System.Array.CopyTo:

  • Es más rápido que Clone al copiar a una matriz del mismo tipo;
  • Llama a Array.Copy heredar es capacidades, siendo las más útiles:
    • Puede encajonar elementos de tipo de valor en elementos de tipo de referencia, por ejemplo, copiando un array int[] en un object[];
    • Puede descomprimir el tipo de referencia elementos en elementos de tipo valor, por ejemplo, copiando una matriz object[] de int en caja en un int[];
    • Puede realizar conversiones ampliadas en tipos de valor, por ejemplo, copiando un int[] en un long[].
    • Puede degradar elementos, por ejemplo, copiando una matriz Stream[] en una MemoryStream[] (si cualquier elemento en la matriz de origen no es convertible a MemoryStream se lanza una excepción).
  • Permite copiar el origen a una matriz de destino que tiene una longitud mayor que la fuente.

También tenga en cuenta, estos métodos están disponibles para apoyar ICloneable y ICollection, así que si usted está tratando con variables de tipos de matriz no debe utilizar Clone o CopyTo y en su lugar utilizar Array.Copy o Array.ConstrainedCopy. La copia restringida asegura que si la operación de copia no puede completarse correctamente, el estado de la matriz de destino no está dañado.

 17
Author: João Angelo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:21
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"

La fuente

 7
Author: GenZiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-14 07:19:25

Tanto CopyTo() como Clone() hacen una copia superficial. El método Clone () hace un clon del array original. Devuelve una matriz de longitud exacta.

Por otro lado, CopyTo() copia los elementos de la matriz original a la matriz de destino comenzando en el índice de matriz de destino especificado. Tenga en cuenta que, esto agrega elementos a una matriz ya existente.

El siguiente código contradice las publicaciones que dicen que CopyTo () hace una copia profunda:

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);
}

Permítanme explicarlo un poco. Si los elementos de la matriz son de tipos de referencia, entonces la copia (tanto para Clone () y CopyTo ()) se hará hasta el primer nivel (superior). Pero el nivel inferior no se copia. Si necesitamos copia de nivel inferior también, tenemos que hacerlo explícitamente. Es por eso que después de Clonar o Copiar elementos de tipo de referencia, cada elemento en la matriz Clonada o copiada se refiere a la misma ubicación de memoria que se refiere el elemento correspondiente en la matriz original. Esto indica claramente que no hay la instancia se crea para el nivel inferior. Y si fuera así, entonces cambiar el valor de cualquier elemento en la matriz Copiada o clonada no tendría efecto en el elemento correspondiente de la matriz original.

Creo que mi explicación es exhaustiva, pero no encontré otra manera de hacerla comprensible.

 2
Author: Prasad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-14 09:37:56

El método Clone() no hace referencia a la instancia de destino, solo le da una copia. el método CopyTo() copia los elementos en una instancia existente.

Ambos no dan la referencia de la instancia de destino y como muchos miembros dicen que dan copia superficial (copia ilusión) sin referencia esta es la clave.

 0
Author: Mohammad Ahmed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-26 14:59:04

Las respuestas me confunden. Cuando dices copia superficial, esto significa que todavía están apuntando a la misma dirección. Lo que significa que cambiar uno de los dos cambiará a otro también.

Así que si tengo A = [1,2,3,4] y lo clono y obtengo B = [1,2,3,4]. Ahora, si cambio B [ 0] = 9. Esto significa que A ahora será A =[9,2,3,4]. ¿Es correcto?

 0
Author: Stranger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-09 17:21:42

Ambas son copias superficiales. El método CopyTo no es una copia profunda. Compruebe el siguiente código :

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 */
 0
Author: Nikhil R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-13 04:35:52

Clone() se utiliza para copiar solo la estructura de datos / matriz no copia los datos reales.

CopyTo() copia la estructura, así como los datos reales.

 -1
Author: abatishchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-14 07:18:49

Tenga en cuenta: Hay una diferencia entre usar String [] a StringBuilder [].

In String - si cambia la Cadena, los otros arrays que hemos copiado (por CopyTo o Clone) que apuntan a la misma cadena no cambiarán, pero el array de cadena original apuntará a una nueva Cadena, sin embargo, si usamos un StringBuilder en un array, el puntero de cadena no cambiará, por lo tanto, afectará a todas las copias que hemos hecho para este array. Por ejemplo:

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
}
 -2
Author: inbaly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-21 10:30:43