하나의 클래스에 여러 개의 생성자를 작성해야 할 때,
각각의 생성자에서 멤버 변수를 초기화 하는 것보다 멤버 초기화 구문
을 사용하는 것이 좋다.
초기화 되지 않은 멤버 변수를 사용하는 문제에서 벗어 날 수 있다.
public class MyClass
{
// 컬렉션을 선언과 동시에 초기화
private List<string> labels = new List<string>();
}
👉 이렇게 하면 각각의 생성자에서 labels를 초기화할 필요가 없어진다.
💡TIP!
컴파일러는 모든 생성자의 시작 부분에 멤버 초기화 구문을 포함시킨다. 새로운 생성자가 추가되거나 사용자가 생성자를 선언하지 않아 기본 생성자가 만들어진 경우에도, 항상 생성자가 실행되기 전 멤버 초기화 구문이 실행된다.
기본 시스템 초기화 루틴은 코드를 실행하기 전에 모든 값을 0으로 설정한다. 이와 같이 저수준의 시스템 초기화 루틴에서 이미 변수의 값을 0으로 설정하기 때문에 추가적으로 변수를 0이나 null로 설정할 필요가 없다.
public struct MyValType
{}
//생략
MyValType myVal1;
MyValType myVal2 = new MyValType(); // 반복해서 0으로 초기화
첫 번째 문장은 myVal1이 사상된 블록을 모두 0으로 설정한다. 두 번째 문장은 initObj라는 IL 명령을 사용하는데 박싱/언박싱된 myVal2변수 모두에 대해서 0으로 초기화하는 과정이 수행된다. 이과정으로 약간의 추가 시간이 소요된다.
멤버 초기화 구문은 객체 생성 방법이 모든 생성자에서 동일한 경우에 사용하는 것이 좋다. 만약 아래 MyClass2와 같이 List 객체를 생성하는 방식이 다양할 경우 멤버 초기화 구문을 사용하지 않는 것이 좋다.
public class MyClass2
{
// 컬렉션을 선언하는 동시에 초기화
private List<string> labels = new List<string>();
MyClass2() { }
MyClass2(int size)
{
labels = new List<string>(size);
}
}
위와 같이 작성할 경우 int 변수 하나를 매개변수로 가지는 생성자가 호출 될 경우 이미 생성되어 있는 labels의 객체가 즉각 가비지가 된다.
멤버 초기화 구문은 try로 감쌀 수 없기 때문에 초기화 과정에서 예외가 발생하면 예외가 외부로 전파된다. 이 경우 생성자 내로 초기화 구문을 옮기고 예외 처리 코드를 적용하는 것이 좋다.