클래스의 구성 요소 중 생성자와 소멸자(종료자)를 다룬다. 개체의 생성과 소멸에 관련된 메서드로, 생성자는 명시적으로 정의하고 호출해서 생성해야 하지만 소멸자는 필요하지 않다면 정의하지 않아도 닷넷 가비지컬렉터(Garbage Collector; GC)가 자동으로 역할을 해준다. 그렇게 어려운 개념은 아니므로 빠르게 다루고 넘어간다.
생성자(Constructor)
클래스 이름과 동일한 이름을 가지는 메서드로, 주로 클래스의 인스턴스를 생성할 때 사용된다. 클래스는 적어도 한 개의 생성자를 가진다. 생성자는 void를 포함한 반환값을 가지지 않음에 주의하자
- 생성자를 사용한 개체 생성 : 클래스 이름과 동일한 이름으로 작성
using System;
class Hello
{
//생성자 : 클래스 이름과 같다
public Hello()
{
Console.WriteLine("Hello Constructor");
}
static void Main()
{
//생성자 호출
Hello h = new Hello();
}
}
- 기본 생성자 : 매개 변수가 없는 생성자
- 위의 예제는 매개 변수가 없는 기본 생성자이기도 하다.
- 매개 변수가 있는 생성자
using System;
class User
{
//User 클래스의 필드
private string _Name;
private int _Age;
//생성자 : 매개 변수를 활용해 필드 값을 초기화
public User(string name, int age)
{
this._Name = name;
this._Age = age;
}
//메서드 : 필드 값 출력
public void GetInfo()
{
Console.WriteLine($"name : {this._Name}, age : {this._Age}");
}
static void Main()
{
//생성자, 메서드 호출
User Kim = new User("김밥", 25);
Kim.GetInfo();
}
}
- 생성자 오버로드(overload) : 생성자 여러 개 만들기
using System;
class User
{
//User 클래스의 필드
private string _Name = "Unknown";
private int _Age = -1;
//기본 생성자
public User()
{
this.GetInfo();
}
//생성자 오버로딩 : 값 1개 받기
public User(string name)
{
this._Name = name;
this.GetInfo();
}
//생성자 오버로딩 : 값 1개 받기
public User(int age)
{
this._Age = age;
this.GetInfo();
}
//생성자 오버로딩 : 값 2개 모두 받기
public User(string name, int age)
{
this._Name = name;
this._Age = age;
this.GetInfo();
}
//메서드 : 필드 값 출력
public void GetInfo()
{
Console.WriteLine($"name : {this._Name}, age : {this._Age}");
}
static void Main()
{
//다양한 생성자 호출
User Lee = new User();
User David = new User("David");
User Lan = new User( 25);
User Kim = new User("김밥", 25);
}
}
생성자 오버로드 기능을 활용해 동일한 클래스로 유연한 초기화를 할 수 있다.
- 정적 생성자와 인스턴스 생성자
- 정적 생성자 (static 키워드) : 클래스의 정적 멤버를 호출할 때 가장 먼저 호출, 매개 변수 없음
- 인스턴스 생성자 (주로 public 키워드) : 일반적인 개체의 인스턴스를 생성
using System;
class User
{
//User 클래스의 필드
private static string _Name;
private int _Age = 20;
//정적 생성자
static User()
{
_Name = "김정적";
}
//인스턴스 생성자
public User( int age)
{
this._Age = age;
}
//정적 메서드 : 이름 값 출력
public static void GetName()
{
Console.WriteLine($"name : {_Name}");
}
//인스턴스 메서드 : 나이 값 출력
public void GetAge()
{
Console.WriteLine($"age : {this._Age}");
}
static void Main()
{
//정적 생성자(자동적으로 먼저 호출됨), 메서드 호출
User.GetName();
//인스턴스 생성자, 메서드 호출
User Kim = new User(25);
Kim.GetAge();
}
}
//출력: name : 김정적 age : 25
- this() 생성자를 활용한 생성자 포워딩(forwarding)
using System;
class User
{
//User 클래스의 필드
private string _Name;
//기본 생성자
public User()
{
this._Name = "김기본";
this.GetName();
}
//this() 생성자를 활용한 생성자 포워딩
public User(string name) : this()
{
this._Name = name;
this.GetName();
}
//메서드 : 이름 값 출력
public void GetName()
{
Console.WriteLine($"name : {_Name}");
}
static void Main()
{
User Kim = new User("김포워딩");
}
}
//출력 : name : 김기본 name : 김포워딩
this() 생성자를 활용해 생성자를 포워딩하는 것으로 다른 생성자에 값을 전달하기 용이하다. 위의 예제 같은 상황 말고도, 택시의 기본 요금을 모범 택시의 기본 요금으로 덮어 씌우는 상황 등에서 활용할 수 있을 것이다. 또한 상속에서 다루는 base()를 사용해 부모 클래스의 생성자에 값을 전달할 수 있다.(상속 관련 포스팅에서 다룰 예정)
- 생성자를 활용한 읽기 전용 필드 초기화
- readonly 키워드를 사용해 정의된 필드는 읽기 전용 필드로, 생성자로만 초기화 가능. 이후 변경 불가
using System;
class User
{
//읽기 전용 필드
private readonly string _Name;
//생성자에서만 읽기 전용 필드를 초기화 가능
public User(string name)
{
this._Name = name;
}
//메서드 : 이름 값 출력
public void GetName()
{
Console.WriteLine($"name : {_Name}");
}
static void Main()
{
User Kim = new User("김읽기전용");
Kim.GetName();
}
}
- 식 본문 생성자(expression bodied constructor) : 람다식의 화살표 연산자를 사용해 생성자를 줄여 표현하는 것
using System;
class User
{
//User 클래스의 필드
private string _Name;
//식 본문 생성자
public User(string name) => this._Name = name;
//메서드 : 이름 값 출력
public void GetName()
{
Console.WriteLine($"name : {_Name}");
}
static void Main()
{
User Kim = new User("김식본문");
Kim.GetName();
}
}
소멸자(Destructor)
클래스 이름 앞에 ~를 붙여 만드는 메서드로, 종료자(finalizer)라고도 한다. 닷넷의 가비지컬렉터(GC)에서 클래스의 인스턴스를 다 사용한 후 정리할 때 실행되는 메서드로, 클래스에서 가장 마지막으로 호출되는 메서드이다. 소멸자는 매개변수를 받을 수 없으며, 오버로드를 지원하지 않고, 직접 호출할 수 없다. 정적 호출, 인스턴스 호출에 상관없이 형태 동일하다.
- 소멸자 설정법 : ~클래스 이름()
using System;
class User
{
//필드
private string _Name;
//생성자
public User(string name) => this._Name = name;
//메서드
public void GetName()
{
Console.WriteLine($"name : {_Name}");
}
//소멸자
~User()
{
Console.WriteLine("유저 정보 폐기");
}
static void Main()
{
User Kim = new User("김소멸자");
Kim.GetName();
//GC.Collect()의 자동적 실행 : ~User() 호출됨
}
}
C#에서는 GC가 존재해, 사용이 끝난 인스턴스를 자동적으로 제거해 메모리를 관리해준다. GC가 사용이 완료된 클래스 인스턴스를 제거할 때 소멸자를 호출한다. 일반적으로는 소멸자를 자주 쓰진 않는다.
'C#' 카테고리의 다른 글
[C#] 부분 클래스와 부분 메서드(partial), 정적 클래스(static) (0) | 2024.05.02 |
---|---|
[C#] 인덱서(Indexer)와 반복기(iterator, yield 키워드), 지연된 연산 (0) | 2024.04.30 |
[C#] 익명 형식(Anonymous Type)과 덕 타이핑(Duck Typing), 개체 이니셜라이저, nameof 연산자 (0) | 2024.04.30 |
[C#] 속성(Property)과 접근자(get, set, init), 읽기/쓰기 전용 속성 (0) | 2024.04.30 |
[C#] 스레드(Thread)와 동기화(lock), 병렬 처리 API(TPL) (0) | 2024.04.29 |
[C#] 람다 식(=>), 입력 매개 변수와 자연 형식 (0) | 2024.04.29 |
[C#] 이벤트(Event) (0) | 2024.04.26 |
[C#] Action, Func, Predicate 제네릭 대리자(델리게이트; Delegate)와 매개변수에 메서드 전달 (0) | 2024.04.26 |