Shallow Copy / Deep Copy




 .Net 에서는 2가지 데이터 타입이 존재한다.
- Value Teyp
- Reference Type

아마도 BCL 을 사용하던, 사용자 정의 클래스를 사용하던 Reference Type 을 사용하는 경우가 대부분 일 텐데, 참조 변수간의 값 할당은 Shallow copy 에 의해서 참조 값이 복사되게 된다. 즉, Managed Heap 에 할당된 하나의 객체를 여러 참조 변수들이 가리키게 된다.


이미지 출처 : C# Object Clone Wars


메모리의 효율적 사용 면에서는 Shallow Copy 에 의한 Clone 을 갖는게 좋을 수 있다. 하지만 경우에 따라서는 독립적인 복사본을 만들어야 되는 경우가 있다.(스레드 사용하면서..)



■ 참조값의 할당 (=)



위와 같이 Person 타입 객체를 참조하는 참조 변수 yuk 가 있을 때 youngho 라는 참조 객체에 yuk 값을 할당 연산자 = 로 값을 대입하면 Shallow Copy 일까, Deep Copy 일까??  난 Shallow Copy 일 거라 추측했지만 Shallow Copy 가 아니다. 단지 yuk 가 참조하던 객체를 youngho 변수도 참조하게 될 뿐이다.



■ Shallow Copy - MemberwiseClone()

Shallow Copy(얕은 복사) 가 참조 타입에 대하여 막연히 객체에 대한 참조를 복사 받는다고 알고 있었는데 Value Type 에 대해 어떤 동작을 하는지는 미처 생각하지 못했다.

1. .Net 에서 Shallow Copy
- 값 타입(Value Type)은 동일한  복사본을 생성
- 참조 타입(Reference Type)은 객체를 가리키는 참조를 리턴 받는다.



즉, Shallow Copy 라고 하더라도, Value Type 에 대해서는 독립적인 메모리를 할당 한다.

.Net 에서 Shallow Copy 를 지원하기 위해 MemberwiseClone() 메소드를 지원한다.



System.Object 의 멤버 이므로 .Net 의 모든 클래스(FCL)들이  MemberwiseClone() 메소드를 갖는다.
protected 접근 제한자를 갖기 때문에 클래스 외부에서 바로 사용할 수는 없고, 클래스 멤버 메소드에서 호출할 수 있다.
사용 예는 다음과 같다.


이미지 출처 :  데브피아 : 객체 복사(깊은 복사/얕은 복사)




■ Deep Copy - ICloneable, Clone()

1. .Net 에서 Deep Copy
- 값 타입, 참조 타입에 관계없이 새로운 복사본을 복사한다.




.Net 에서는 Deep Copy 를 지원하기 위해 ICloneable 인터페이스를 이용한 Close() 메소드를 지원한다.







ICloneable 인터페이스는 System 네임스페이스안에 정의 되어 있으며 Clone() 이라는 하나의 메소드를 갖는다.
요약 설명대로 하나의 인스턴스에 대해서 동일한 새로운 인스턴스를 생성하여 리턴한다. 이때 리턴 타입은 object 타입이다.

MSDN 문서에 따르면 ICloneable 의 Clone() 메소드가 Deep Copy 를 수행한다고 명시적으로 연급되어 있지는 않는다.
cf) C# Object Clone Wars

사용 예는 다음과 같다.


이미지 출처 : 데브피아 : 객체 복사(깊은 복사/얕은 복사)



■ History

1. 2009.10.31 - posting


 
■ 참조

1. C# Object Clone Wars
2. 데브피아 : 객체 복사(깊은 복사/얕은 복사)
Posted by six605

댓글을 달아 주세요

  1. 최익필 2010.07.20 01:31 신고  댓글주소  수정/삭제  댓글쓰기

    Value Type 이면서 멤버로 Reference Type을 갖을 경우,
    1. ICloneable 을 사용 하는게 좋을까요?
    2. Reference Type 만 봅사 하는 방법을 제공해 주는게 좋을까요?

    현재 이 고민 중에 있습니다.

    • 최익필 2010.07.20 01:54 신고  댓글주소  수정/삭제

      자답입니다. 2번이 더 좋다고 생각 됩니다.
      왜냐하면 value type에 reference type을 포함했다는것 자체가 이미 특별한 상태라고 보여지기 때문입니다.

      이런 상태라면
      1. boxing/unboxing 을 value type에서 clone()으로 할 이유가 없음
      2. Clone() 이라는 관리 코드를 염두해야 하는 부담을 없앨 수 있음

      이상입니다.

    • six605 2010.07.20 08:52 신고  댓글주소  수정/삭제

      아... 리플을 늦게 확인했네요 죄송 ㅠㅠ

      음.. Value Type 이면서 Reference Type을 갖는 경우라면
      대표적인 경우가 구조체겠군요!!

      요즘 Effective C# 을 보고 있는데 책의 내용을 보면
      ICloneable의 구현을 피하라고 하는군요.

      리플로 남겨주신 내용이 맞는것 같습니다. ^^