2010-04-30 5 views
8

다양한 개체 유형의 다양한 ObservableCollection이 있습니다. 이러한 객체 유형 중 하나의 컬렉션을 취하여 각 컬렉션이 지정된 컬렉션에있는 요소의 전체 복사본 인 새 컬렉션을 반환하는 단일 메서드를 작성하고 싶습니다. 특정 클래스의 예는 다음과 같습니다컬렉션의 모든 요소에 대한 전체 복사본을 만드는 일반적인 방법

private static ObservableCollection<PropertyValueRow> DeepCopy(ObservableCollection<PropertyValueRow> list) 
    { 
     ObservableCollection<PropertyValueRow> newList = new ObservableCollection<PropertyValueRow>(); 
     foreach (PropertyValueRow rec in list) 
     { 
      newList.Add((PropertyValueRow)rec.Clone()); 
     } 
     return newList; 
    } 

이 방법을 ICloneable을 구현하는 모든 클래스에 대해 일반화하려면 어떻게해야합니까?

+4

공정한 경고로서 모든 ICloneable 구현이 실제로 딥 복사본이있는 것은 아닙니다. –

답변

24

이 같은 것을 할 수있는 :

private static ObservableCollection<T> DeepCopy<T>(ObservableCollection<T> list) 
    where T : ICloneable 
{ 
    ObservableCollection<T> newList = new ObservableCollection<T>(); 
    foreach (T rec in list) 
    { 
     newList.Add((T)rec.Clone()); 
    } 
    return newList; 
} 

참고가 IEnumerable<T>을 복용하여보다 일반적인 만들 수 있으며, LINQ는 심지어 쉽게 :

private static ObservableCollection<T> DeepCopy<T>(IEnumerable<T> list) 
    where T : ICloneable 
{ 
    return new ObservableCollection<T>(list.Select(x => x.Clone()).Cast<T>()); 
} 
+1

나는 그것을 시도했지만 일반적인 방법을 고려하지 않는 것 같습니다. "제약 조건이 아닌 일반 선언에 허용되지 않습니다"컴파일러 오류가 발생합니다. – bwarner

+1

죄송합니다 - 오타가 있습니다. 메소드 이름 끝에' '이 필요하다. –

+1

은 Jon Skeet에 대한 Chuck Norris 유형의 모든 농담을 읽었으므로 Jon Skeet이 실수로 오타를 가지고 있다는 사실을 믿기가 어렵습니다. 그러나 정말로 아름다운 포스트. 깔끔한 두 번째 LINQ 기반 버전을 가져 주셔서 감사합니다. 산뜻한. 아주 깔끔한. –

3
private static ObservableCollection<T> DeepCopy<T>(ObservableCollection<T> list) 
    where T : ICloneable 
{ 
    ObservableCollection<T> newList = new ObservableCollection<T>(); 
    foreach (T rec in list) 
    { 
     newList.Add((T)rec.Clone()); 
    } 
    return newList; 
} 
+2

이것은 Jon Skeet의 게시물의 "Cloned"버전 인 것 같습니다 :-) –

+8

14:15에 수정 한 13:26에 올바른 버전으로 코드를 "복제"했다고 생각합니까? 타임머신을 가지고 있지 않습니다. – Hinek

+0

+1 타임머신 용 :) – WiiMaxx

0

나는를 사용 구현할 수있는 모든 ICollections와 작동하는 매우 유사한 함수 (예 : 많은 표준 컬렉션) :

public static TContainer CloneDeep<TContainer, T>(TContainer r) 
     where T : ICloneable 
     where TContainer: ICollection<T>, new() 
    { 
     // could use linq here, but this is my original pedestrian code ;-) 
     TContainer l = new TContainer(); 
     foreach(var t in r) 
     { 
      l.Add((T)t.Clone()); 
     } 

     return l; 
    } 

컴파일러는 유감스럽게도 유형을 추론하여 명시 적으로 전달해야합니다. 소수의 전화 외에도 나는 전문 분야를 씁니다. 다음은 Lists (암시 적으로 추론 된 T로 호출 될 수있는)의 예입니다.

public static List<T> CloneListDeep<T>(List<T> r) where T : ICloneable 
    { 
     return CloneDeep<List<T>, T>(r); 
    } 

I는 취소 될 수 datagridviews 다이얼로그에 대한 데이터 소스로서리스트의 사본을 생성하기 위해 광범위이 기능을 사용한다. 수정 된 목록은 대화 상자가 취소 될 때 간단히 버려집니다. 대화 상자가 OK 일 때 편집 된 목록은 단순히 원본을 대체합니다. 물론이 패턴의 전제 조건은 의미 상으로 정확하고 잘 관리 된 것입니다. T.clone().

관련 문제