728x90
깊은 복사(Deep Copy)
- 깊은 복사는 객체의 값을 완전히 새로운 메모리 공간에 복사하는 방식이다. 따라서 원본 객체과 복사된 객체가 독립적으로 존재하고, 어느 한 쪽에서 변경이 일어나도 다른 쪽에 영향을 미치지 않는다.
- 예시
public struct PersonStruct
{
public string Name;
}
PersonStruct person1 = new PersonStruct { Name = "Tom" };
PersonStruct person2 = person1; // 값 복사이므로 깊은 복사
person2.Name = "Bob"; // 깊은 복사이므로 복사해온 객체에 대해 영향 X
Console.WriteLine(person1.Name); // 출력 : Alice
Console.WriteLine(person2.Name); // 출력 : Bob
C#에서 구조체는 값 형식(value type)이므로 struct를 생성하면 새로운 객체의 값이 그대로 변수에 저장된다. 따라서 위와 같은 상황에서는 깊은 복사가 일어나게 되고, 하나의 값을 변경해도 다른 값에 영향을 미치지 않는다.
얕은 복사(Shallow Copy)
- 얕은 복사는 객체의 참조 주소만 복사하는 방식이다. 따라서 원본 객체의 필드 중 참조 타입(배열, 리스트, 클래스와 같은 사용자 정의 객체 등)은 원본과 복사본이 같은 객체를 가리키게 된다.
단, 값 타입 필드(int, bool, double 등)은 복사된다. - 예시
public class Person
{
public string name;
}
Person person1 = new Person { Name = "Tom" };
Person person2 = person1; // 얕은 복사가 일어남
person2.Name = "Bob"; // 얕은 복사이므로 같은 객체를 가리켜 person1에도 영향을 미침
Console.WriteLine(person1.Name); // 출력 : Bob
C#에서 클래스는 참조 타입(reference type)이기 때문에 new 키워드를 통해 생성하면, 새로운 객체에 대한 참조가 반환된다. 따라서 위와 같이 객체를 new로 생성한 뒤 복사를 하게 되면, 참조만 복사하게 되는 얕은 복사가 일어나게 되고, 하나의 값을 바꾸면 다른 값에도 영향을 미치게 된다.
참조 형식을 깊은 복사로 복제하는 방법
직접 클래스 내에 구현
- 참조 타입 필드를 새롭게 할당하고, 각 필드를 직접 복사해주는 방법이다.
- 예시
public struct IdInfo
{
public int IdNumber;
public IdInfo(int IdNumber)
{
this.IdNumber = IdNumber;
}
}
public class Person
{
public int Age;
public string Name;
public IdInfo IdInfo;
public Person ShallowCopy()
{
return (Person)this.MemberWiseClone();
}
public Person DeepCopy()
{
Person other = (Person)this.MemberWiseClone();
other.IdInfo = new IdInfo(IdInfo.IdNumber);
other.Name = String.Copy(Name);
return other;
}
}
여기서 MemberwiseClone 메서드는 객체를 새로운 메모리에 할당하여 독립적인 객체로 복제하는 메서드이다.
이 과정에서 객체의 멤버도 복제되는데 값 형식(value type) 데이터는 제대로 깊은 복사가 되지만 참조 형식 데이터는 얕은 복사가 된다.
따라서 참조 형식의 멤버를 깊은 복사하는 코드를 별도로 구현해야 한다.
Serialize / Deserialize (직렬화 / 역직렬) 사용
- JSON, Binary, XML 직렬화를 통해 객체를 완전히 새로운 인스턴스로 바꿀 수 있다.
- 예시
public class Person
{
public string Name;
public List<string> Hobbies;
public Person DeepCopy()
{
var json = JsonSerializer.Serialize(this); // json 형식으로 직렬화
return JsonSerializer.Deserialize<Person>(json); // 역직렬화
}
}
이 때 JSON 직렬화를 사용하려면 클래스와 필드가 직렬화가 가능해야 하며, [Serializable] 또는 public 접근 수준을 가져야 한다.
728x90
'언어(C, C++, C#)' 카테고리의 다른 글
[C#] .NET, 컴파일 과정, CLS, CTS, CIL, CLI, CLR, JIT 컴파일 (1) | 2024.11.06 |
---|---|
[C#] 접근 제한자(public, private, protected, internal 등) (0) | 2024.11.06 |
[C#] Virtual, Abstract, Interface (0) | 2024.11.05 |
[C#] this (2) | 2024.11.05 |
[C#] object와 var (0) | 2024.11.04 |