04
25
다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.

 

 

C#에서는 객체 초기화를 위한 코드가 반복되는 것을 막기 위해 생성자 체인 기법을 제공한다.

 

생성자 체인

 - 임의의 생성자가 동일 클래스 내의 정의된 다른 생성자를 호출하는 방식.

 - 기본값을 가진 생성자를 추가 생성해두고, 다른 생성자를 호출하여 코드 중복을 최소화 한다.

public class MyClass
{
    private int count ;
    private string name;

    public MyClass() : this(0, "")
    {
    }
    
    public MyClass(int count) : this(count, string.Empty)
    {
    }
    
    public MyClass(int count, string name)
    {
        this.count = count;
        this.name = name;
    }
}

 

생성자 체인의 호출순서

 - 아래와 같이 클래스를 작성한 뒤, 오버로딩 생성자를 호출해보면 호출 순서를 알 수 있다.

public class MyClass
{
    static MyClass()
    {
        Debug.Log("정적 생성자");
    }

    public MyClass(int count) : this()
    {
        Debug.Log("오버로딩 생성자");
    }

    public MyClass()
    {
        Debug.Log("일반 생성자");
    }
}

 

내부에서 함수를 호출하는 방식은?

 - 비슷해 보이지만 코드 중복을 제거하지 못해 비효율적이다.

 - 인스턴스 변수 초기화 -> 베이스 클래스 생성자 -> 공용 유틸리티 함수 호출의 순으로 코드가 추가되는데, 이 과정에서 함수를 호출하는 방식은 인스턴스 변수 초기화, 베이스 클래스 생성자의 중복이 발생한다.

 - 생성자 체인 방식에서는 마지막에 호출된 생성자에서만 인스턴스 변수 초기화와 베이스 클래스 생성자가 추가된다.

 - 또한 일반 함수는 생성자가 아니기 때문에 readonly 필드를 초기화하지 못한다.

public class MyClass
{
    private int count ;
    private string name;

    public MyClass()
    {
        CommonConstructor(0, "");
    }
    
    public MyClass(int count)
    {
        CommonConstructor(count, "");
    }
    
    public MyClass(int count, string name)
    {
        CommonConstructor(count, name);
    }
    
    private void CommonConstructor(int count, string name)
    {
        this.count = count;
        this.name = name;
    }
}

 

인스턴스를 생성할 때 수행되는 과정

 - 클래스의 초기화는 한 번만 일어나기 때문에, 동일한 타입으로 추가 인스턴스가 발생하면 5단계부터 수행된다.

1. 정적 변수의 저장 공간을 0으로 초기화
2. 정적 변수에 대한 초기화 구문 수행
3. 베이스 클래스의 정적 생성자 수행
4. 정적 생성자 수행
5. 인스턴스 변수의 저장 공간을 0으로 초기화
6. 인스턴스 변수에 대한 초기화 구문 수행
7. 적절한 베이스 클래스의 인스턴스 생성자 수행
8. 인스턴스 생성자 수행

 

결론

 - 생성자 체인 말고도 선택적 인자를 사용하여 초기값을 정해두는 것도 좋다.

 - 특히 중요한 건 정적 필드 초기화 -> 정적 생성자 -> 일반 필드 초기화 -> 정적 필드 초기화의 호출 순서.

 

 

COMMENT