System.Array.CopyTo()
과 의 차이점은 무엇입니까 System.Array.Clone()
?
System.Array.CopyTo()
과 의 차이점은 무엇입니까 System.Array.Clone()
?
답변:
클론 () 메소드는 새로운 어레이 원의 배열에있는 모든 요소를 포함하는 (a 얕은 복사) 객체를 반환한다. 하는 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>
작동합니다.
다른 많은 답변에서 언급했듯이 두 방법 모두 배열의 얕은 복사본 을 수행 합니다. 그러나 아직 해결되지 않은 차이점과 권장 사항이 다음 목록에 강조 표시되어 있습니다.
의 특성 System.Array.Clone
:
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
. 제한된 복사는 복사 작업을 성공적으로 완료 할 수없는 경우 대상 스토리지 상태가 손상되지 않도록합니다.
.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
또는 문자열 의 배열을 참조로 메서드에 전달할 때 기술적으로 깊은 복사를 수행 합니다.
예를 들면
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 번 줄에서 동일한 정렬되지 않은 초기 형식이됩니다.
참고 : 복제는 정렬 방법에서 수행되어야합니다.
대답이 혼란 스럽습니다. 얕은 복사라고하면 여전히 동일한 주소를 가리키고 있음을 의미합니다. 즉, 둘 중 하나를 변경하면 다른 것도 변경됩니다.
따라서 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 []로 사용하는 것에는 차이가 있습니다.
String에서-String을 변경하면 동일한 문자열을 가리키는 CopyTo 또는 Clone으로 복사 한 다른 배열은 변경되지 않지만 원래 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
대 와 관련이 없습니다 Clone
. 참조 의미론과 값 의미론 일뿐입니다. int는 값 유형이므로 매번 새 복사본을 얻습니다. StringBuilder에는 참조 의미 체계가 있으므로 동일한 복사본에서 작업하고 있습니다.