[C#] 얕은복사 & 깊은복사
클래스는 참조형식이다.
참조 형식은 힙 영역에 객체를 할당하고 스택에 있는 참조가 힙 영역에 할당된 메모리를 가리킨다.
값형식, 참조형식: https://zheldajdajd.tistory.com/10
[C#] 변수와 데이터 타입 (값형식, 참조형식)
변수와 데이터 타입 (값형식, 참조형식) 목차 1. 변수 2. 값형식, 참조형식 3. 기본 데이터 타입 1. 변수 프로그래밍에서의 변수(Variable)란 데이터를 담는 일정 크기의 공간을 의미한다. 변수는 보통
zheldajdajd.tistory.com
예제를 하나 살펴보자.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Csharp_Project
{
class ShallowCopy
{
public int ShallowField;
public int ShallowField2;
}
class MainApp
{
public static void Main()
{
ShallowCopy source = new ShallowCopy();
source.ShallowField = 1;
source.ShallowField2 = 2;
ShallowCopy source2 = source; //source를 source2에 복사
source2.ShallowField2 = 3;
Console.WriteLine("source.ShallowField1: {0} / source.ShallowField2: {1}",
source.ShallowField, source.ShallowField2);
Console.WriteLine("source2.ShallowField1: {0} / source2.ShallowField2: {1}",
source2.ShallowField, source2.ShallowField2);
}
}
}
source객체에 값을 할당한 후, source2 객체에 source를 복사해주었다.
source객체의 변수에는 1과 2라는 값을 할당하였으므로 source2의 변수에도 동일한 값이 할당되었을 것이다.
그런데 여기서 source2.ShallowField2에 3이란 값을 할당해주었다.
그렇다면 source의 ShallowField2값은 어떻게 될까? 이 코드에서 바꿔준건 source2 객체의 값이므로 sourc의 값은 변동이 없을까?
예상과는 source객체에 할당된 값도 변해버렸다.
앞서 언급했듯 클래스는 참조형식을 사용한다.
이러한 상태인 source를 복사해서 source2에 할당해주면...
이런 상태가 되는 것이다.
이렇게 스택에 있는 참조만 복사해버리면 source와 source2는 같은 영역을 참조하게 되고 source2의 값을 바꾸면 source의 값도 바뀌어버리는 일이 일어나는 것이다.
이것을 얕은 복사(Shallow Copy)라고 한다.
그렇다면 위와 같이 source에서 복사한 내용을 별도의 힙 공간에 보관하기 위해서는 어떻게 해야할까?
한 번 구현해보자.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Csharp_Project
{
class DeepCopy
{
public int DeepField1;
public int DeepField2;
public DeepCopy Copy()
{
DeepCopy newCopy = new DeepCopy();
newCopy.DeepField1 = this.DeepField1;
newCopy.DeepField2 = this.DeepField2;
return newCopy;
}
}
class MainApp
{
public static void Main()
{
DeepCopy source = new DeepCopy();
source.DeepField1 = 1;
source.DeepField2 = 2;
DeepCopy source2 = source.Copy();
source2.DeepField2 = 3;
Console.WriteLine("source.DeepField1: {0} / source.DeepField2 {1}",
source.DeepField1, source.DeepField2);
Console.WriteLine("source2.DeepField1: {0} / source2.DeepField2 {1}",
source2.DeepField1, source2.DeepField2);
}
}
}
<실행 결과>
무사히 복사되었다. 위 코드에서 사용된 this는 객체가 자기 자신을 가리킬때 사용하는 키워드이다.
즉, 객체 내부에서 자기 자신의 필드나 메소드를 접근할때 사용한다.
Copy() 메소드에서는 객체를 새로운 힙에 할당하여 (위 코드의 newCopy) 해당 힙에 자기 자신(this 키워드)의 멤버를 일일이 복사해 넣는다.
이러한 방식을 객체의 깊은 복사 라고 한다.