ref out 게시글에서 복사와 참조에 대하여 잠깐 다뤘었다.
C++ 게시글에서 심도 있게 다루었던 내용이지만, C#에서도 한번 정리하고 넘어가야 맘이 편할 것 같아서
이번 게시글에서는 복사와 참조, 깊은 복사에 대해 다뤄보려고 한다.
Struct 복사, Class 참조
우선 c#에서 struct는 기본적으로 복사를 하고, class는 참조를 한다.
예시를 통해 살펴보자.
using System.Numerics;
namespace CSharp
{
class Program
{
class Warrior
{
public int hp;
public int attack;
public void Move()
{
Console.WriteLine("Warrior Move");
}
public void Attack()
{
Console.WriteLine("Warrior Attack");
}
}
struct Mage
{
public int hp;
public int attack;
public void Move()
{
Console.WriteLine("Mage Move");
}
public void Attack()
{
Console.WriteLine("Mage Attack");
}
}
static void KillMage(Mage mage)
{
mage.hp = 0;
}
static void KillWarrior(Warrior warrior)
{
warrior.hp = 0;
}
static void Main(string[] args)
{
Mage mage = new Mage();
mage.hp = 100;
mage.attack = 50;
KillMage(mage);
Warrior warrior = new Warrior();
warrior.hp = 100;
warrior.attack = 20;
KillWarrior(warrior);
Console.WriteLine($"Mage hp : {mage.hp}");
Console.WriteLine($"Warrior hp : {warrior.hp}");
}
}
}
각각 Warrior class와 Mage struct를 만들어 주었다.
멤버 변수로 각각 hp와 attack을 가지고 있고 Move(), Attack() 함수를 가지고 있다 (예시이기 때문에 출력만!).
그리고 hp를 0으로 만들어 주는 KillMage() 함수와 KillWarrior() 함수를 만들어 주었다.
그리고 각각의 Warrior 와 Mage를 할당해 준 다음 hp에는 100의 값을 넣어 초기화 해 주었다.
프로그램을 실행하여 출력 결과를 보면
mage의 hp는 여전히 100, warrior의 hp는 여전히 0이다.
이것은 처음에 언급한 대로, class는 무조건 참조를 통해 변수의 값을 전달하게 되고
(참조는 진퉁, 주소값을 통해 진짜 변수를 전달한 것),
struct는 복사를 통해 변수의 값을 전달하기 때문에 이런 결과가 나오는 것이다
(복사는 가짜, 상식적으로 어떤 것을 복사를 했는데 그 복사물을 변형했다고 원래 본체가 바뀔 리가 없잖아!).
+ 추가로 우리는 이 struct의 매개변수 앞에 ref를 붙일 경우 참조로 바뀐다는 것을 이전 게시글에서 배웠다.
이번에는 main함수의 내용만 조금 바꿔서, mage2, warrior2 변수를 새로 만들어서 실험해 보자.
static void Main(string[] args)
{
Mage mage = new Mage();
mage.hp = 100;
mage.attack = 50;
Mage mage2 = mage;
mage2.hp = 0;
Warrior warrior = new Warrior();
warrior.hp = 100;
warrior.attack = 20;
KillWarrior(warrior);
Warrior warrior2 = warrior;
warrior.hp = 0;
Console.WriteLine($"Mage hp : {mage.hp}");
Console.WriteLine($"Mage2 hp : {mage2.hp}");
Console.WriteLine($"Warrior hp : {warrior.hp}");
Console.WriteLine($"Warrior2 hp : {warrior2.hp}");
}
mage2의 hp에 0을 대입했을 때 mage2는 단순히 mage를 복사한 것이니까 mage의 hp에는 변화가 없으니 100이 된다.
하지만 위에서 언급했듯 class는 참조로 변수를 넘기기 때문에 별도로 변수를 조작하지 않았음에도 둘 모두 hp가 0이 되는 것을 확인할 수 있다.
깊은 복사 (Deep Copy)
완전히 분리된 객체를 만들어 주기 위해 깊은 복사 기법을 활용해 보자.
(간단한 설명 - 깊은 복사: 데이터 자체를 통으로 복사해서 독립적인 메모리를 가진 값을 만들어 주는 것)
Warrior class 안에 Clone() 함수를 만들어 주었다.
class Program
{
class Warrior
{
public int hp;
public int attack;
public Warrior Clone()
{
Warrior warrior = new Warrior();
warrior.hp = hp;
warrior.attack = attack;
return warrior;
}
}
struct Mage
{
public int hp;
public int attack;
}
static void Main(string[] args)
{
Warrior warrior = new Warrior();
warrior.hp = 100;
warrior.attack = 20;
Warrior warrior2 = warrior.Clone();
warrior2.hp = 0;
Console.WriteLine($"Warrior hp : {warrior.hp}");
Console.WriteLine($"Warrior2 hp : {warrior2.hp}");
}
}
Clone()의 역할은,
Clone()함수를 호출했을 때 새로운 Warrior을 만들어 준 다음 들고 있던 hp와 attack을 그대로 넣어서 초기화 해주고 반환해주는 역할이다.
문제 없이 독립적인 Warrior 변수들이 만들어졌음을 알 수 있다.
*이 포스트는 스택과 힙 포스트로 내용이 이어집니다. 함께 학습해야 정확히 이해할 수 있습니다.
https://nybot-house.tistory.com/101
'C# 기초 프로그래밍 > C# Basic' 카테고리의 다른 글
[C# Basics] 재귀 함수 (0) | 2024.06.11 |
---|---|
[C# Basics] 다형성 (polymorphism) - OOP의 핵심 개념 (0) | 2024.04.15 |
[C# Basics] 캡슐화 / 은닉성 - OOP 의 핵심 개념(객체 지향 프로그래밍) (0) | 2024.04.12 |
[C# Basics] 객체지향 OOP란 무엇인가? - 핵심 4개념과 개론 (0) | 2024.04.12 |
[C# Basics] 생성자 Constructor (0) | 2024.04.02 |
[C# Basics] 스택과 힙 정리 - feat.복사와 참조, value, reference (0) | 2024.04.01 |
<C# Basics> ref, out 키워드 (0) | 2023.12.11 |
<C# Basics> 함수/메서드 (2) | 2023.12.11 |