¿Cuál es la diferencia entre System.Array.CopyTo()
y System.Array.Clone()
?
¿Cuál es la diferencia entre System.Array.CopyTo()
y System.Array.Clone()
?
Respuestas:
El método Clone () devuelve un nuevo objeto de matriz (una copia superficial) que contiene todos los elementos de la matriz original. El método CopyTo () copia los elementos en otra matriz existente. Ambos realizan una copia superficial. Una copia superficial significa que el contenido (cada elemento de la matriz) contiene referencias al mismo objeto que los elementos de la matriz original. Una copia profunda (que no realiza ninguno de estos métodos) crearía una nueva instancia del objeto de cada elemento, dando como resultado un objeto diferente pero idéntico.
Entonces 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 incorrecto.
numbersCopy
es solo otra referencia al arreglo asignado a numbers
. Esto no es lo mismo que usar el CopyTo()
método. Si lo usa CopyTo()
, obtendrá los mismos resultados que en su Clone()
ejemplo. Además, esto es C #, System.out.println
debería serlo Console.WriteLine
.
ToArray()
método de Linq proporciona una forma mucho más simple (y mecanografiada ) de clonar un arreglo superficial de todos modos. Dado que Array es IENumerable<T>
, funciona en él.
Otra diferencia no mencionada hasta ahora es que
Clone()
la matriz de destino no es necesario que exista todavía, ya que se crea una nueva desde cero.CopyTo()
no sólo la necesidad matriz de destino ya de existir, tiene que ser lo suficientemente grande para contener todos los elementos de la matriz de origen desde el índice especificado como destino.Como se indica en muchas otras respuestas, ambos métodos realizan copias superficiales de la matriz. Sin embargo, existen diferencias y recomendaciones que aún no se han abordado y que se destacan en las siguientes listas.
Caracteristicas de System.Array.Clone
:
CopyTo
probablemente porque usa Object.MemberwiseClone
;Caracteristicas de System.Array.CopyTo
:
Clone
cuando se copia en una matriz del mismo tipo;Array.Copy
heredar sus capacidades , siendo las más útiles:
int[]
matriz en un object[]
;object[]
matriz de encuadrados int
en un int[]
;int[]
en un long[]
.Stream[]
matriz en un MemoryStream[]
(si cualquier elemento en la matriz fuente no es convertible a MemoryStream
una excepción, se lanza).También tenga en cuenta que estos métodos están disponibles para admitir ICloneable
y ICollection
, por lo que si está tratando con variables de tipos de matriz, no debe usar Clone
o CopyTo
y en su lugar use Array.Copy
o Array.ConstrainedCopy
. La copia restringida asegura que si la operación de copia no se puede completar correctamente, el estado de la matriz de destino no está dañado.
.ToArray()
método de Linq . Hace una copia de todos modos y se puede ejecutar en cualquiera IEnumerable<>
, incluidas las matrices. Y a diferencia .Clone()
, está escrito, por lo que no se necesita casting.
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, le CopyTo
permite copiar una matriz a un índice específico en la matriz de destino, lo que le da una flexibilidad significativamente mayor.
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"
Tanto CopyTo () como Clone () hacen una copia superficial. El método Clone () hace un clon de la matriz 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 la 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);
}
Déjame explicarte un poco. Si los elementos de la matriz son de tipos de referencia, entonces la copia (tanto para Clone () como para CopyTo ()) se realizará hasta el primer nivel (superior). Pero el nivel inferior no se copia. Si también necesitamos una copia de nivel inferior, tenemos que hacerlo explícitamente. Es por eso que después de la clonación o copia de elementos de tipo de referencia, cada elemento de la matriz clonada o copiada se refiere a la misma ubicación de memoria a la que hace referencia el elemento correspondiente en la matriz original. Esto indica claramente que no se crea una instancia separada para el nivel inferior. Y si fuera así, cambiar el valor de cualquier elemento en la matriz Copiado o Clonado no tendría efecto en el elemento correspondiente de la matriz original.
Creo que mi explicación es exhaustiva pero no encontré otra forma de hacerla comprensible.
Array.Clone()
realizaría una copia técnicamente profunda, cuando pasa la matriz int
o cadena a un método como referencia.
Por ejemplo
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
Incluso si los métodos clasifican la matriz de números, pero no afectará la referencia real pasada a los métodos de clasificación, es decir, la matriz de números estará en el mismo formato inicial sin clasificar en la línea no 1.
Nota: El clon debe realizarse en los métodos de clasificación.
El Clone()
método no hace referencia a la instancia de destino, solo le da una copia. el CopyTo()
método copia los elementos en una instancia existente.
Ambos no dan la referencia de la instancia de destino y como muchos miembros dicen que dan una copia superficial (copia de ilusión) sin referencia, esta es la clave.
Las respuestas me confunden. Cuando dices copia superficial, esto significa que todavía apuntan a la misma dirección. Lo que significa que cambiar cualquiera de ellos cambiará también a otro.
Entonces, 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 eso correcto?
Ambos son copias superficiales. El método CopyTo no es una copia profunda. Verifique 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 */
Array.Clone no requiere que haya una matriz de destino / destino disponible al llamar a la función, mientras que Array.CopyTo requiere una matriz de destino y un índice.
Clone()
se usa para copiar solo la estructura de datos / matriz, no copia los datos reales.
CopyTo()
copia la estructura y los datos reales.
Tenga en cuenta: existe una diferencia entre usar String [] y StringBuilder [].
En String: si cambia el String, las otras matrices que hemos copiado (por CopyTo o Clone) que apuntan a la misma cadena no cambiarán, pero la matriz de String original apuntará a una nueva String, sin embargo, si usamos un StringBuilder en una matriz, el puntero de cadena no cambiará, por lo tanto, afectará a todas las copias que hemos realizado para esta matriz. 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
}
CopyTo
vs Clone
. Es solo semántica de referencia frente a semántica de valor. int es un tipo de valor, por lo que obtiene una nueva copia cada vez. StringBuilder tiene semántica de referencia, por lo que está actuando sobre la misma copia.