C# 개체 복제 전쟁

4874 단어 ICloneable
Clone 방법은 효과에 따라 딥 클론(deep cloning)과 얕은 클론(shallow cloning)으로 나눌 수 있다.복제를 실현하는 수단도 매우 많은데, 스스로 번거로운 복제 방법을 실현하고 반사, 서열화, 심지어 기존의 복제 구조를 이용하는 것을 포함한다
C# 클론 객체는 "트랩"이 많기 때문에 쉽고 어려워 보이는 일입니다.이 문서에서는 가장 일반적인 C# 객체 복제 방법에 대해 설명합니다.
얕은 복사와 깊은 복사
두 가지 대상 복제 방법이 있는데 그것이 바로 얕은 복사와 깊은 복사이다.얕은 복사는 인용만 복제할 뿐 인용의 대상은 복제하지 않습니다.깊이 복사는 인용된 대상을 복제합니다.
따라서 원시 대상의 인용과 얕은 복사 대상의 같은 인용은 모두 같은 대상을 가리킨다.깊이 복사된 대상은 대상의 모든 직간접적인 인용을 포함한다.위키백과를 참고하여 더 많은 해석을 얻다.
 
ICloneable 커넥터
ICloneable 인터페이스에는 현재 객체의 복사본을 만드는 데 사용할 수 있는 Clone 메서드가 포함되어 있습니다.
public interface ICloneable {
    object Clone();
}
ICloneable의 문제는 Clone 방법이 얕은 복사나 깊은 복사를 실행하는 것으로 현저하게 지정되지 않기 때문에 호출자가 실제 상황을 확정할 수 없다는 것이다.그래서 ICloneable를NET 프레임워크에서 탈락된 토론.MSDN 문서는 Clone 메서드가 딥 카피임을 암시하는 것처럼 보이지만 문서에 명확한 설명이 없습니다.
ICloneable 인터페이스에는 MemberWiseClone이 제공하는 기능을 초과하여 지원하는 구성원 방법이 포함되어 있습니다.MemberWiseclone은 얕은 복사를 진행합니다.
유형 보안 클론
ICloneable의 또 다른 단점은 Clone 방법이 하나의 대상을 되돌려주기 때문에 Clone을 호출할 때마다 강제 형식 변환을 해야 한다는 것이다.
Person joe = new Person();
joe.Name = "Joe Smith";
Person joeClone = (Person)joe.Clone();
강제 유형 변환을 피할 수 있는 방법은 자신의 유형을 안전하게 제공하는 Clone 방법입니다.주의해라, 너는 여전히 ICloneable을 제공해야 한다.Clone 메서드는 iCloneable 인터페이스 요구 사항을 충족합니다.
public class Person : ICloneable {
    public string Name;
    object ICloneable.Clone()
    {
        return this.Clone();
    }
    public Person Clone()
    {
        return (Person)this.MemberwiseClone();
    }
}
클론 방법 선택
1. 수동 복제
대상이 당신이 생각하는 대로 완전히 복제될 수 있도록 보장하는 방법은 수동으로 복제된 대상의 모든 필드 (field) 이다.이런 방식의 단점은 번거롭고 오류가 발생하기 쉽다는 것이다. 클래스에 영역을 추가하면 클론을 업데이트하는 방법을 잊어버릴 수도 있다.또한 복제 인용 대상이 원시 대상을 가리킬 때 무한 순환 인용을 피하는 것을 주의해야 한다.다음은 심층 복제의 간단한 예입니다.
public class Person : ICloneable {
    public string Name;
    public Person Spouse;
    public object Clone()
    {
        Person p = new Person();
        p.Name = this.Name;
        if (this.Spouse != null)
            p.Spouse = (Person)this.Spouse.Clone();
        return p;
    }
}
2. MemberWiseclone 메서드 사용
MemberWiseclone은 Object 클래스의 보호 방법입니다. 새 대상을 만들고 현재 대상의 모든 비정상적인 영역을 새 대상에 복사해서 얕은 복사본을 만들 수 있습니다.값 유형의 도메인에 대해서는 비트별 복제가 수행됩니다.인용 형식의 영역에 대해 인용은 값이 부여되고 인용된 대상은 인용되지 않습니다.따라서 원본 객체와 클론은 동일한 객체를 참조합니다.이 방법은 파생 클래스에 효과가 있습니다. 즉, 기본 클래스에서 Clone 방법을 한 번만 정의하면 됩니다.다음은 간단한 예입니다.
public class Person : ICloneable {
    public string Name;
    public Person Spouse;
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}
3. 반사로 클론 만들기
반사로 클론 복제는 Activator를 사용합니다.CreateInstance 메서드는 동일한 유형의 새 객체를 만든 다음 모든 도메인을 반사하여 얕게 복사합니다.이 방법의 장점은 완전 자동이어서 대상에 구성원을 추가하거나 삭제할 때 클론 방법을 수정할 필요가 없다는 것이다.또 깊은 복사를 제공하는 방법으로 쓰일 수도 있다.단점은 반사를 사용했기 때문에 비교적 느리고 일부 신뢰를 받는 환경에서는 사용할 수 없다는 것이다.예제 코드
4. 클론을 시리얼화하기
대상을 복제하는 가장 간단한 방법은 그것을 서열화하고 즉시 새로운 대상으로 반서열화하는 것이다.반사법과 마찬가지로 서열화 방법은 자동적이며 대상 구성원을 삭제할 때 수정할 필요가 없다.단점은 서열화가 다른 방법보다 느리고 심지어 반사하는 것보다 느리며 모든 인용 대상은 서열화되어야 한다는 것이다.또한 사용자가 사용하는 서열화된 형식 (XML, SOAP, 이진) 에 따라 개인 구성원이 기대했던 대로 복제되지 않을 수도 있습니다.예시 코드는 여기, 여기와 여기.
5. IL을 사용한 클론 복제
객체 복제에 IL(중간 언어)을 사용하는 것은 드문 해결책입니다.이런 식으로 동적 방법 (Dynamic Method) 을 만들고 중간 언어 생성기 (ILGenerator) 를 가져와 방법에 코드를 주입해서 의뢰로 컴파일한 다음 이 의뢰를 실행합니다.의뢰는 캐시되기 때문에 중간 언어는 처음 복제할 때만 생성되며 후속 복제는 다시 생성되지 않습니다.비록 이런 방법은 사용반사보다 빠르지만 이런 방법은 이해하고 유지하기 어렵다.예제 코드
6. 확장 방법을 사용하여 클론 생성
Havard Stranden은 확장 방법(extention method)으로 사용자 정의 클론 프레임워크를 만듭니다.이 프레임워크는 대상 구조가 아무리 복잡해도 대상과 인용된 대상의 깊은 복사를 만들 수 있다.단점은 원본 코드를 제공하지 않는 사용자 정의 프레임워크 (업데이트: 현재 원본 코드가 포함되어 있습니다. 본 논문 평론 참조) 이며, 파라미터 구조기를 사용하지 않을 때 개인적인 방법으로 만든 대상을 복사할 수 없습니다.또 다른 문제는 모든 자동화된 심층 복제 방법이 공통적으로 가지고 있는 문제이다. 심층 복제는 일반적으로 단순하고 자동화된 특수한 상황 (예를 들어 관리되지 않은 자원) 을 유연하게 처리해야 한다는 것이다.

좋은 웹페이지 즐겨찾기