using System.ComponentModel;
using System.Numerics;
using System.Threading;
namespace CSharp
{
// 참조
class Knight
{
public int hp;
public int attack;
public void Move()
{
Console.WriteLine("Knight Move");
}
public void Attack()
{
Console.WriteLine("Knight Attack");
}
public Knight Clone()
{
Knight knight = new Knight();
knight.hp = this.hp; // 현재 객체의 hp를 복사
knight.attack = this.attack; // 현재 객체의 attack을 복사
return knight; // 복사된 객체 반환
}
}
// 복사
struct Mage
{
public int hp;
public int attack;
}
internal class Program
{
// 복사와 참조
static void KillMage(Mage mage)
{
mage.hp = 0;
}
static void KillKnight(Knight knight)
{
knight.hp = 0;
}
static void Main(string[] args)
{
Mage mage;
mage.hp = 100;
mage.attack = 10;
KillMage(mage);
Mage mage2 = mage;
mage2.hp = 0;
Knight knight = new Knight();
KillKnight(knight);
knight.hp = 100;
knight.attack = 10;
knight.Move();
knight.Attack();
//Knight knight2 = knight;
//knight.hp = 0;
//Knight knight2 = new Knight();
//knight2.hp = knight.hp;
//knight2.attack = knight.attack;
// DeepCopy(깊은 복사)
Knight knight2 = knight.Clone();
knight2.hp = 0;
}
}
}
| 구분 | 구조체(Struct) | 클래스(Class) |
|---|---|---|
| 타입 | 값 타입(Value Type) | 참조 타입(Reference Type) |
| 메모리 저장 위치 | 스택(Stack) | 힙(Heap) |
| 복사 방식 | Call by Value (값 복사) | Call by Reference (주소 복사) |
| 할당 방식 | Mage mage; 선언만으로 메모리 할당됨 | Knight knight; 선언만으로는 메모리 할당 X (new 필수) |
| 객체 복사 | 새로운 객체가 생성됨 (독립적인 사본) | 기본적으로 참조가 복사됨 (같은 객체를 공유) |
| 사용 사례 | 간단한 데이터 저장 | 객체의 동작과 상태를 관리 |
✅ 구조체(Struct) → 값 타입이므로 독립적인 복사본을 생성
✅ 클래스(Class) → 참조 타입이므로 동일한 객체를 공유 (얕은 복사)
struct Mage
{
public int hp;
public int attack;
}
✅ 구조체는 값 타입(Value Type)으로, 복사 시 새로운 독립적인 객체가 생성됨
✅ 스택(Stack) 메모리에 저장 → Mage mage2 = mage; 하면 새로운 메모리가 할당됨
✅ Mage 구조체를 복사하면 hp와 attack 값이 그대로 복사되지만, 두 객체는 서로 영향을 주지 않음
Mage mage;
mage.hp = 100;
mage.attack = 50;
Mage mage2 = mage; // 값 복사
mage2.hp = 0; // mage2의 hp만 변경, 원본 mage는 영향 없음
class Knight
{
public int hp;
public int attack;
}
✅ 클래스는 참조 타입(Reference Type)으로, 복사 시 같은 객체를 가리킴
✅ 힙(Heap) 메모리에 저장 → Knight knight = new Knight(); 해야 객체가 생성됨
✅ Knight knight2 = knight; 하면 knight2와 knight는 같은 객체를 공유
Knight knight = new Knight();
knight.hp = 100;
knight.attack = 10;
Knight knight2 = knight; // 얕은 복사
knight2.hp = 0; // knight2의 hp를 변경하면 knight도 변경됨
➡ knight2는 knight와 동일한 객체를 참조하기 때문에 하나를 변경하면 나머지도 변경됨 (얕은 복사).
public Knight Clone()
{
Knight knight = new Knight();
knight.hp = this.hp;
knight.attack = this.attack;
return knight;
}
✅ Clone() 메서드를 사용하여 새로운 객체를 생성하고 모든 속성을 복사
✅ Knight knight2 = knight.Clone(); 하면 knight2는 knight와 독립적인 객체
Knight knight = new Knight();
knight.hp = 100;
knight.attack = 10;
Knight knight2 = knight.Clone(); // 깊은 복사
knight2.hp = 0; // knight2의 hp만 변경됨, knight는 영향 없음
static void KillMage(Mage mage)
{
mage.hp = 0; // mage 구조체를 복사하여 사용 (원본 영향 없음)
}
static void KillKnight(Knight knight)
{
knight.hp = 0; // knight 객체의 참조를 전달받아 원본이 변경됨
}
✅ 구조체(값 타입) → KillMage(mage);를 호출해도 원본 mage는 변경되지 않음
✅ 클래스(참조 타입) → KillKnight(knight);를 호출하면 원본 knight의 hp가 0으로 변경됨
Mage mage;
mage.hp = 100;
KillMage(mage); // 호출 후에도 mage.hp == 100 (영향 없음)
Knight knight = new Knight();
knight.hp = 100;
KillKnight(knight); // 호출 후 knight.hp == 0 (원본 변경됨)