[Effective C# - ITEM 12] 할당 구문보다 멤버 초기화 구문이 좋다

백지혜·2022년 8월 14일
1

Effective C#

목록 보기
1/1
post-thumbnail

하나의 클래스에 여러 개의 생성자를 작성해야 할 때,
각각의 생성자에서 멤버 변수를 초기화 하는 것보다 멤버 초기화 구문을 사용하는 것이 좋다.

✅ 멤버 초기화 구문

초기화 되지 않은 멤버 변수를 사용하는 문제에서 벗어 날 수 있다.

public class MyClass
{
    // 컬렉션을 선언과 동시에 초기화
    private List<string> labels = new List<string>();
}

👉 이렇게 하면 각각의 생성자에서 labels를 초기화할 필요가 없어진다.

💡TIP!
컴파일러는 모든 생성자의 시작 부분에 멤버 초기화 구문을 포함시킨다. 새로운 생성자가 추가되거나 사용자가 생성자를 선언하지 않아 기본 생성자가 만들어진 경우에도, 항상 생성자가 실행되기 전 멤버 초기화 구문이 실행된다.

✅ 멤버 초기화 구문의 특징

  • 멤버 초기화 구문은 각 생성자의 앞쪽에 자동으로 추가된다.
  • 베이스 클래스의 생성자가 호출되기 전에 초기화된다.
  • 멤버 변수의 초기화 순서는 변수 선언 순서이다.

✅ 멤버 초기화 구문을 사용하지 않아야 할 경우

  1. 0이나 null로 초기화하는 경우 (기본 초기화 루틴과 같기 때문)
  2. 동일한 객체를 반복해서 초기화하는 경우 (객체가 두번 생성되어 가비지가 발생한다)
  3. 예외 처리가 반드시 필요한 경우 (멤버 초기화 구문은 try로 감쌀 수 없다)

1. 객체를 0이나 null로 초기화하는 경우

기본 시스템 초기화 루틴은 코드를 실행하기 전에 모든 값을 0으로 설정한다. 이와 같이 저수준의 시스템 초기화 루틴에서 이미 변수의 값을 0으로 설정하기 때문에 추가적으로 변수를 0이나 null로 설정할 필요가 없다.

public struct MyValType
{}
//생략
MyValType myVal1;
MyValType myVal2 = new MyValType(); // 반복해서 0으로 초기화

첫 번째 문장은 myVal1이 사상된 블록을 모두 0으로 설정한다. 두 번째 문장은 initObj라는 IL 명령을 사용하는데 박싱/언박싱된 myVal2변수 모두에 대해서 0으로 초기화하는 과정이 수행된다. 이과정으로 약간의 추가 시간이 소요된다.

2. 동일한 객체를 반복해서 초기화하는 경우

멤버 초기화 구문은 객체 생성 방법이 모든 생성자에서 동일한 경우에 사용하는 것이 좋다. 만약 아래 MyClass2와 같이 List 객체를 생성하는 방식이 다양할 경우 멤버 초기화 구문을 사용하지 않는 것이 좋다.

public class MyClass2
{
  // 컬렉션을 선언하는 동시에 초기화
  private List<string> labels = new List<string>();
 
  MyClass2() {    }
 
  MyClass2(int size) 
  {
    labels = new List<string>(size);
  }
}

위와 같이 작성할 경우 int 변수 하나를 매개변수로 가지는 생성자가 호출 될 경우 이미 생성되어 있는 labels의 객체가 즉각 가비지가 된다.

3. 멤버 초기화할 때 예외 처리가 필요한 경우

멤버 초기화 구문은 try로 감쌀 수 없기 때문에 초기화 과정에서 예외가 발생하면 예외가 외부로 전파된다. 이 경우 생성자 내로 초기화 구문을 옮기고 예외 처리 코드를 적용하는 것이 좋다.

⭐정리⭐

  • 멤버 초기화 구문을 이용하면 타입 내에 생성자가 여러 개일 때도 멤버 변수 초기화를 누락하지 않도록 도와준다.
  • 다만, 모든 생성자가 동일한 방법으로 멤버 변수를 초기화하는 경우에 한해서만 이 방법을 사용해야한다.
profile
hello world!

0개의 댓글