1) 절차(Procedure)지향 : 함수(메소드)로 구현
- 장점 : 굉장히 심플함
- 단점 : 함수의 실행순서에 종속적어서 유지보수 힘듬, 프로그램이 거대해질수록 유지보수 힘들고 로직이 꼬일수 있음
2) 객체(OOP : Object Oriented Programming)지향 : 모든것을 객체로 생각함
- 속성, 기능 구성
- ex) Knight
- 속성 : hp, attack, pos
- 기능 : Move, Attack, Die
3) 클래스와 구조체의 차이
- 클래스 : 기본적으로 참조(Ref)를 해서 넘김
- 구조체 : 기본적으로 복사(Copy)를 해서 넘김(정적할당, 동적할당시에도 복사로 적용됨)
4) 얕은복사(Shallow Copy)와 깊은복사(Deep Copy)
- 얕은복사 : 참조를 복사
클래스는 참조 형식이다. 그렇기 때문에 다음과 같이 복사를 해주면 문제가 발생한다.
class Monster
{
public int hp;
public int damage;
public Monster(int hp, int damage)
{
this.hp = hp;
this.damage = damage;
}
}
Monster myMonster = new Monster(100, 5);
Monster otherMonster = myMonster; // 얕은 복사
otherMonster.hp = 200;
Console.WriteLine($"myMonster HP : {myMonster.hp}");
Console.WriteLine($"otherMonster HP : {otherMonster.hp}");

객체는 하나만 생성하고 그걸 가리키는 참조 변수는 두 개(myMonster, otherMonster)가 된 것이다. 그러니, otherMonster의 체력을 변경해도 myMonster의 체력이 같이 변경되는 일이 벌어졌다.
즉, 제대로된 복사를 해주려면 새로운 객체를 생성해고 내부 값들을 복사하여 넘겨주는 깊은 복사 작업이 필요하다.
- 깊은복사 : 데이터 값 전체를 복사
C#에서는 깊은 복사를 자동으로 해주는 구문이 없기 때문에 직접 만들어 줘야 한다.
class Monster
{
public int hp;
public int damage;
public Monster(int hp, int damage)
{
this.hp = hp;
this.damage = damage;
}
public Monster DeepCopy() // 깊은 복사 메소드 생성
{
Monster newMonster = new Monster(0, 0);
newMonster.hp = this.hp;
newMonster.damage = this.damage;
return newMonster;
}
}
Monster myMonster = new Monster(100, 5);
Monster otherMonster = myMonster.DeepCopy(); // 깊은 복사
otherMonster.hp = 200;
Console.WriteLine($"myMonster HP : {myMonster.hp}");
Console.WriteLine($"otherMonster HP : {otherMonster.hp}");

새로운 객체를 만들어서 내부값들을 복사해주고 리턴하는 DeepCopy() 라는 메소드를 만들었다. 이제 myMonster와 otherMonster는 서로 다른 객체를 참조하고 있다.
- 참고 : ICloneable 인터페이스를 활용하여 깊은 복사를 만들 수도 있다
학습본문
using System;
using System.Numerics;
namespace Rookiss_CSharp
{
class Program
{
class Knight
{
// 기본적으로 접근지정자는 internal로 됨(에셈블리 내에서만 접근됨)
// int hp;
// internal int hp;
public int hp;
public int attack;
/// <summary>
/// 깊은복사
/// 새롭게 동적할당 + 값 복사후 resturn
/// </summary>
/// <returns></returns>
public Knight Clone()
{
Knight knight = new Knight();
knight.hp = this.hp;
knight.attack = this.attack;
return knight;
}
public void Move()
{
Console.WriteLine("Knight Move");
}
public void Attack()
{
Console.WriteLine("Knight Attack");
}
}
struct Mage
{
public int hp;
public int attack;
}
static void KillMage(Mage mage)
{
mage.hp = 0;
}
static void KillKnight(Knight knight)
{
knight.hp = 0;
}
static void Main(string[] args)
{
// Mage mage;
Mage mage = new Mage();
mage.hp = 100;
mage.attack = 50;
KillMage(mage); // 구조체라서 값 복사로 넘어감(원본 수정필요시 ref 필요) => Mage mage;, Mage mage = new Mage();로 해도 동일
Mage mage2 = mage; // 복사라서 mage의 hp 그대로고, mage2의 hp: 10이됨(mage와, mage2는 별도라고 생각하면 됨)
mage2.hp = 10;
Knight knight = new Knight();
knight.hp = 100;
knight.attack = 10;
KillKnight(knight); // 클래스라서 기본적으로 참조로 넘어감(ref 명시 안해줘도, ref로 연산함)
Knight knight2 = knight; // 참조라서 knight의 hp: 10이됨(참조라서 knight2와 knight가 동일시됨)
knight2.hp = 10;
Knight knight3 = knight.Clone(); // 깊은복사
}
}
}
참조
복사(값)와 참조 | [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part1: C# 기초 프로그래밍 입문
복사(값)와 참조
www.inflearn.com
35강 객체지향의 시작 ~ 36강 복사(값)와 참조
얕은복사와 깊은복사
[C#] 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) + ICloneable 인터페이스
*이 글은 책을 바탕으로 공부한 글입니다. C#의 클래스 부분을 공부하고 있었다. 어떤 객체지향언어를 배우든 클래스와 생성자란 개념이 나왔고, 이것은 익숙하게 알고 있는 내용이었다. 이번에
daekyoulibrary.tistory.com
'C# > 기본 문법' 카테고리의 다른 글
| C# 생성자 (0) | 2025.11.01 |
|---|---|
| C# 메모리 영역 (0) | 2025.11.01 |
| C# TextRPG (0) | 2025.11.01 |
| C# 간단한 연습문제 (0) | 2025.10.27 |
| C# 기초 문법 정리 - 함수 (0) | 2025.10.27 |