# 멤버 초기화 구문이 좋은 이유 

 

. 생성자가 여러 개일 때도 멤버 변수 초기화를 누락하지 않도록 미연에 방지할 수 있다.

  (다만, 모든 생성자가 동일한 방법으로 멤버 변수를 초기화하는 경우에 한해서 사용해야 한다. )

 

. 가독성이 좋고, 유지보수도 용이하다. 

 

 

 

 

# 초기화 구문의 특성

 

. 컴파일러는 모든 생성자(생성자가 없는 경우에 생성하는 기본생성자 포함)의 시작 부분에 멤버 초기화 구문을 포함시키기 때문에 새로운 생성자를 추가하더라도 항상 멤버 초기화 구문이 포함된다.

 

. 또한, 생성하려는 타입이 클래스를 상속하고 있는 경우 베이스 클래스의 생성자가 호출되기 전에 멤버에 대한 초기화가 이루어진다.

 

. 멤버 변수의 초기화 순서는 변수의 선언 순서이다.

 

 

 

 

# 사용 방법

 

  변수를 선언하는 곳에 변수를 초기화 하도록 작성하기만하면 된다.

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

 

 

 

 

# 주의해야할 경우

 

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

 

  기본 시스템 초기화 루틴은 코드를 실행하기 전에 모든 값을 0으로 설정한다.

그런데 객체를 0이나 null로 초기화 하게되면, C#컴파일러는 개의치 않고 코드를 생성하기 때문에 괜한 일을 추가적으로 하는 꼴이 된다.

public struct MyValType
{
    // 생략
}

MyValType myVal1; // 0으로 초기화
MyValtype myVal2 = new MyValType(); // 반복해서 0으로 초기화

  myVal2같은 경우 initobj라는 IL 명령을 사용하는데 박싱/언박싱 된 myVal2 변수 모두에 대해서 0으로 초기화 하는 과정이 수행된다.

이 과정으로 인해 약간의 추가 시간이 소요된다.

 

 

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

public class MyClass2
{
    private List<string> labels = new List<string>();

    MyClass2() {    }

    MyClass2(int size) 
    {
        labels = new List<string>(size);
    }
}

  위와 같이 List 객체를 생성하는 방식이 다양하게 혼재하는 경우 멤버 초기화 구문을 사용하지 않는 것이 좋다.

MyClass2를 생성할 때 컬렉션의 크기를 지정하게 되면 실제로 2개의 List<> 객체가 생성되며 그 중 하나는 즉각 가비지가 된다.

  멤버 초기화 구문은 생성자의 본문보다 앞서 수행되므로 생성자 본문에서 생성한 객체만 살아남는다.

 

 

3. 예외처리가 반드시 필요한 경우.

 

  멤버 초기화 구문은 try로 감쌀 수 없기 때문에 초기화 과정에서 예외가 발생하면 예외가 외부로 전파된다. 따라서 클래스 내부에서 복구를 시도할 수가 없다.

  예외처리가 필요하다면 반드시 생성자 내부에서 처리해야만 한다.

 

+ Recent posts