[ 개요 ]
인스턴스를 생성할 때 자동으로 호출되는 함수가 있다.
GameCharacter warrior = new GameCharacter();
앞선 클래스 파트에서 인스턴스를 생성할 때 이런 코드를 봤었을 것이다.
new 키워드 뒤에 오는 GameCharacter()가 바로 생성자이다.
이번에는 생성자가 무엇인지 알아보고 그와 한 쌍을 이루는 소멸자가 무엇인지 알아보도록 하겠다.
[ 생성자란 ]
인스턴스 생성 시 자동으로 호출되는 함수로서 인스턴스 초기화 메서드라고 불린다.
어떤 인스턴스든 꼭 가지고 있는 메서드이다.
생성자에는 두 가지 종류가 있다.
- 기본 생성자(default constructor)
- 직접 정의한 생성자
기본 생성자는 사용자가 직접 생성자를 정의하지 않아도 자동으로 만들어지며 아무런 작동을 하지 않는 생성자이다.
앞선 클래스 파트에서 생성자를 따로 구현한게 없어보였는데
GameCharacter warrior = new GameCharacter();
이렇게 사용할 수 있었던 것도 기본 생성자가 있었기 때문이다.
그럼 직접 정의하는 생성자에 대해서도 알아보자
[ 생성자 구현 방법 ]
두 가지 규칙을 지켜주면 된다.
- 생성자의 이름은 클래스의 이름과 동일해야 한다.
- 생성자는 반환값이 없어야 한다.
클래스명(){
//초기화할 값 or 없어도 됨
}
일단 메서드 선언에서 반환형을 사용하지 않는다.
메서드 안에서 초기화를 해줘도 되지만 없어도 괜찮다(없으면 디폴드 생성자와 동일)
class GameCharacter
{
public string Name; //이름
public GameCharacter(){
Name = "여행자"; //이름 초기화
}
//자신의 이름을 말하는 함수
public void TalkMyName(){
Console.WriteLine("내 이름은 "+Name);
}
}
만약 클래스명이 GameCharacter라면 생성자의 이름도 GameCharacter가 된다.
생성자 안에서 멤버 변수 Name을 “여행자”라는 값으로 초기화하였다.
클래스명(자료형 변수명){
멤버변수 = 변수명
}
위와 같이 입력값을 받아서 초기화 시켜줄 수 있다.
class GameCharacter
{
public string Name; //이름
public GameCharacter(string name){
Name = name;
}
//자신의 이름을 말하는 함수
public void TalkMyName(){
Console.WriteLine("내 이름은 "+Name);
}
}
생성자에 string name이라는 인자를 받아서 멤버 변수 Name에 초기화 시켜준 것을 볼 수 있다.
꼭 생성자 안에 멤버 변수를 초기화하라는 법은 없고 다양하게 사용할 수 있다.
[ 생성자 사용 방법 ]
클래스명 인스턴스명 = new 클래스명();
new 키워드를 사용하여 클래스명() 즉 생성자를 사용하면 된다.
클래스명 인스턴스명 = new 클래스명(인자);
만약 생성자가 인자를 받는다면 인자를 넣어줄 수 있다.
class ProgramClass
{
public static void Main()
{
GameCharacter character = new GameCharacter();
character.TalkMyName();
}
}
class ProgramClass
{
public static void Main()
{
GameCharacter character = new GameCharacter("여행자");
character.TalkMyName();
}
}
위의 두 가지 코드 예시처럼 생성자가 인자를 받지 않으면 생성자 안에 아무것도 안 넣고 호출하면 되고 인자를 받는다면 인자를 넣어 호출하면 된다.
[ 소멸자 ]
인스턴스가 메모리에서 해제될 때 자동으로 호출되는 메서드이다.
생성자와 반대라고 생각하면 이해하기 쉬울 것이다.
생성자에서 동적으로 할당된 메모리를 소멸자를 통해 해제한다고 생각하면 된다.
왜 소멸자를 사용해야 할까?
만약 동적으로 할당된 메모리를 해제하지 않는다면 메모리 누수가 발생할 수 있다.
클래스의 안전성과 효율성을 보장하기 위해 소멸자가 중요하다.
[ 소멸자 구현 방법 ]
두 가지 규칙을 지켜주면 된다.
- 소멸자의 이름은 클래스의 이름과 동일해야 하고 앞에 ‘~’을 붙여야 한다.
- 소멸자는 반환값이 없어야 한다.
- 소멸자는 클래스 별로 하나의 소멸자만을 가진다.
~클래스명(){
//메모리 해제하는 코드
}
~GameCharacter(){
//메모리 해제하는 코드
}
[ 소멸자 사용 방법 ]
소멸자의 사용은 특별히 없다.
인스턴스가 소멸하면 자동으로 호출이 된다.
using System;
class GameCharacter
{
public string[] ItemBox = new string[2]; // 세미콜론 추가
public GameCharacter(string item1, string item2)
{
ItemBox[0] = item1;
ItemBox[1] = item2;
Console.WriteLine("생성자 호출");
}
~GameCharacter()
{
Array.Clear(ItemBox);
Console.WriteLine("소멸자 호출");
}
}
class ProgramClass
{
public static void Main()
{
GameCharacter character = new GameCharacter("한손무기", "방패");
return;
}
}
위와 같은 코드가 있다고 하자
인스턴스를 생성하면 생성자를 호출한다.
그리고 Main 메서드가 종료되면 인스턴스가 사라지면서 소멸자를 호출할 것이다.

그러나 결과를 보면 “생성자 호출” 밖에 나오지 않는다.
아마 C,C++과 같은 언어로 구현했다면 “소멸자 호출”이라는 결과도 호출되었을 것이다.
그러나 .Net5 이상의 C#은 소멸자를 실행시키지 않는데 이유는 가비지 컬렉터(Garbage Collector)가 알아서 해결해 주기 때문이다.
나중에 깊게 다뤄볼 생각인데 간단히 말하자면 사용하지 않는 객체의 메모리를 GC(Garbage Collector)가 주기적으로 검사해서 청소해 준다.
자동으로 청소하는 건 좋은데 그 실행 시점이 GC가 판단해서 처리하니까 우리가 원하는 메모리 해제 지점을 예측하기가 어렵다.
using System;
class GameCharacter
{
public string[] ItemBox = new string[2]; // 세미콜론 추가
public GameCharacter(string item1, string item2)
{
ItemBox[0] = item1;
ItemBox[1] = item2;
Console.WriteLine("생성자 호출");
}
~GameCharacter()
{
Array.Clear(ItemBox);
Console.WriteLine("소멸자 호출");
}
}
class ProgramClass
{
public static void Main()
{
Temp();
GC.Collect();
}
public static void Temp(){
GameCharacter character = new GameCharacter("한손무기", "방패");
}
}
그래서 위의 코드는 GC를 강제로 수집하도록 구현하였다.
Temp()를 통해 character 인스턴스를 지역변수처럼 생성과 해제하게 만들고
GC.Collect()를 이용하여 강제 수집하도록 명령하였다.

GC가 호출되면서 메모리에 할당된 것을 수거해가며 소멸자를 호출한 것을 알 수 있다.
'C#문법' 카테고리의 다른 글
| [C#문법] Part15 this 키워드 (2) | 2024.10.12 |
|---|---|
| [C#문법] Part14 new 연산자 (7) | 2024.10.09 |
| [C#문법] Part12 클래스(Class) (2) | 2024.10.04 |
| [C#문법] 객체지향(Object Oriented Programming)이란 (2) | 2024.10.04 |
| [C#문법] Part11 구조체(struct) (0) | 2024.10.04 |