C# - 얕은 복사, 깊은 복사

Justin·2022년 11월 3일
0

C#

목록 보기
6/7

왜 공부하게 되었나

지난 시간에 Struct Class의 차이를 공부하면서 스텍에서 복사되고, 힙에 저장된 값만 가르킨다는 내용이 있었는데 그 부분이 얕은 복사, 깊은 복사이기에 더 디테일한 정리를 위해 공부한다.

얕은 복사

얕은 복사를 이해하기 전에 이 간단한 문제를 풀어보면 좋을 거 같다. 아래와 같은 코드가 있을 때 출력되는 값은 무엇일까?

class TestClass
{
    public class Person
    {
        public int _weight;
        public int _height;
    }

    static void Main(string[] args)
    {
        Person jason = new Person
        {
            _height = 180,
            _weight = 80
        };

        Person mack = jason;
        mack._height = 170;

        Console.WriteLine("{0}, {1}", jason._height, jason._weight);
        Console.WriteLine("{0}, {1}", mack._height, mack._weight);
    }
}

1번

구분1번
Jason180, 80
Mack170, 80

2번

구분2번
Jason170, 80
Mack170, 80

정단은 2번이다. 왜 일까?

클래스틑 레퍼런스 타입이며 힙 영역에 저장 된다. 하지만 여기서 jason이라는 변수 자체가 힙 영역에 저장 된게 아니라 jason은 힙 영역에 저장 된 값을 가르키고 있는 것 뿐이다.

그래서 mack = jason 을 하게 되면 jason이 가르키던 값을 mack도 가르키게 되고 서로 같은 값을 가르킨 후, mack의 값을 변경 해주니 힙에 저장 되어있던 원본의 값을 변경해주게 되므로 두 값 모두가 변경 된 것이다. 이게 얕은 복사의 개념이다.

깊은 복사

그렇지만 Person 이라는 클래스를 통해 객체를 구분해서 비슷한 사람을 만들고 싶다. 위 예시 처럼 얕은 복사가 아닌 각 데이털 별도의 힙 공간에 새로운 객체를 담아두고 싶을 때는 깊은 복사가 필요하다.

어떻게 할 수 있을까?

아쉽게 C#에는 이를 지원하는 기능은 없고, 스스로 이를 구현 해야 한다. 위에서 만든 Class에 간단하게 깊은 복사를 하는 클래스를 만들어 준다.

public class Person
    {
        public int _weight;
        public int _height;
        public Person DeepCopy()
        {
            Person aPerson = new Person();
            aPerson._weight = this._weight;
            aPerson._height = this._height;
            return aPerson;
        }
    }

해당 함수를 호출 하게 되면 new를 통해 힙 영역에 새로운 객체를 할당하고, 새롭게 마련된 공간에 기존에 가지고 있던 값들을 넣으면서 복사를 하게 된다.

static void Main(string[] args)
    {
        Person jason = new Person
        {
            _height = 180,
            _weight = 80
        };

        Person mack = jason.DeepCopy();
        mack._height = 170;

        Console.WriteLine("{0}, {1}", jason._height, jason._weight);
        Console.WriteLine("{0}, {1}", mack._height, mack._weight);
    }

만들어진 기능을 통해서 jason의 값을 깊은 복사 해주고, 키를 변경하면 이제는 얕은 복사 처럼 모두 변경 되는게 아닌 mack의 height 값만 변경된다.


++ ICloneable 인터페이스

C#에 있는 인터페이스 중 ICloneable 이라는 인터페이스가 위와 같은 깊은 복사를 위한 함수 틀을 만들어 두었기에 다른 이들과 함께 작업할 때는 해당 인터페이스를 상속 받아 사용하는 것도 좋은 방안이 될 것 같다.

profile
인디 게임을 만들며 공부하고 있습니다.

0개의 댓글