2013-10-08 2 views
0

.ToArray()를 사용하여 List의 전체 사본으로 배열을 만들 때 문제가 있습니다. 여기 리스트 <T> .ToArray()가 예상대로 작동하지 않습니다.

내 테스트 클래스입니다 :

public class MyClass 
{ 
    public Color Color1; 
    public MyClass(Color color) 
    { 
     this.Color1 = color; 
    } 
} 

그리고 여기에 내가

List<MyClass> listColors = new List<MyClass>(); 
listColors.Add(new MyClass(Color.Blue)); 
listColors.Add(new MyClass(Color.Green)); 
listColors.Add(new MyClass(Color.Red)); 

MyClass[] arrayColors = listColors.ToArray(); 
arrayColors[2].Color1 = Color.Purple; 

Console.WriteLine(arrayColors[2].Color1.ToString()); 
Console.WriteLine(listColors[2].Color1.ToString()); 

결과 목록의 ToArray()를 수행하는 데 사용하는 코드입니다 :

Color [Purple] 
Color [Purple] 

은 보시다시피, 나는 배열을 만든 MyClass .ToArray() 메서드를 다음이 배열의 요소를 3 변경하지만 왜 목록 listColors 역시 변경되었습니다.

.NET 2.0을 사용하여이 샘플을 Windows XP에서 실행합니다.

나는 윈도우 7에이 샘플을 실행하려고 여기 결과입니다

Color [Purple] 
Color [Red] 

그래서 나는,이 .NET 프레임 워크의 문제라고 생각은.

어쨌든 .NET 2.0에서 .NET 4와 같은 List의 전체 복사본을 만들 수 있습니까? 이것은 단지 시험 수업 일뿐입니다. 제 일은 더 커요.

대단히 감사합니다.

+1

.ToArray()가 새로운 컬렉션을 만들 구현해야하지만, 새로운 객체를 생성하지 않습니다 . 실제로 같은 대상을 수정하고 있습니다. – drch

+2

예를 다시 확인하십시오. .NET 4에서이 결과를 얻었고 첫 번째 결과를 얻었습니다. 이유는 무엇인지 설명하고 있습니다. – kobigurk

+0

사본이 얼마나 있습니까? (Bee Gees pun을 변명하십시오) – Jodrell

답변

2

당신은 생성되지 않은 새로운 MyClass의 객체 (당신의 예상 결과를 제공하는)이 시도 : 코드에서

List<MyClass> listColors = new List<MyClass>(); 
listColors.Add(new MyClass(Color.Blue)); 
listColors.Add(new MyClass(Color.Green)); 
listColors.Add(new MyClass(Color.Red)); 

MyClass[] arrayColors = listColors.ToArray(); 
arrayColors[2] = new MyClass(Color.Purple); 

Console.WriteLine(arrayColors[2].Color1.ToString()); 
Console.WriteLine(listColors[2].Color1.ToString()); 

당신이 컬러 레드를 포함하는 MyClass에 개체의 속성을 변경의 MyClass의 객체가 리스트와 배열 모두에서.

+0

제가 말했듯이,이 클래스는 테스트 클래스입니다. 사실, 클래스가 더 크고 복잡하기 때문에 arrayColors [2] = new MyClass (Color.Purple); 좋은 해결책이 아닙니다. 고맙습니다! –

+0

자신의 기능으로 arraylist를 깊게 복사 할 수 있습니다. 이렇게하면 새로운 MyClass 객체가 생깁니다. 'Color [Purple]'을 두 번 본 이유는 분명합니다. 당신이 고치는 방법은 당신에게 달려 있습니다. – Peter

0

ToArray()는 최소한 사용자가 기대하는 바는 아니지만 전체 복사본을 수행하지 않습니다. 동일한 객체를 가진 배열을 만듭니다. 주제에 대해 내가 아는 가장 좋은 설명은 MSDN입니다.

즉, 원본 및 대상 목록/배열이 모두 참조 형식 인 경우 얕은 복사본이 수행됩니다. 즉, 배열에 동일한 참조가 들어 있음을 의미합니다. 따라서 원래 개체를 변경하고 있습니다.

0

자, 여기 .Net 2.0에서 작동하는 몇 가지 일반적인 방법이 있습니다. 필요한 것을 가져 가라.

public static IList<T> DeepToList<T>(IEnumerable<T> source) where T : IClonable 
{ 
    IList<T> result = new List<T>(); 
    foreach (T t in source) 
    { 
     result.Add((T)t.Clone()); 
    } 

    return result; 
} 

public static T[] DeepToArray<T>(IEnumerable<T> source) where T : IClonable 
{ 
    IList<T> clones = DeepToList(source); 
    T[] result = new T[clones.Count]; 
    clones.CopyTo(result, 0); 
    return result; 
} 

public static T[] DeepToArray<T>(IList<T> source) where T : IClonable 
{ 
    T[] result = new T[source.Count]; 
    for (int i = 0; i < source.Count; i++) 
    { 
     result[i] = (T)source[i].Clone(); 
    } 

    return result; 
} 

을 사용하려면, MyClassIClonable 그래서

public class MyClass : IClonable 
{ 
    public Color Color1; 
    public MyClass(Color color) 
    { 
     this.Color1 = color; 
    } 

    public object Clone() 
    { 
     return new MyClass(this.Color1); 
    } 
} 

당신이 할 수

MyColor[] arrayColors = DeepToArray(listColors) 
+0

나는 이것을 사용할 수 없다고 생각하므로 C# 2.0 개발을 사용하고 있습니다. 고맙습니다. –

+0

@HanTran, Linq 또는 Extension을 제거했으며 .Net 2.0에 대한 코드를 테스트했습니다. – Jodrell

관련 문제