티스토리 뷰
[Effective C# Item 14] 초기화 코드가 중복되는 것을 최소화해라
코딩을 하다가 한 클래스에 생성자를 여러개 작성할 때 종종 동일한 작업을 되풀이할 때가 있어서 기존에 작성한 코드를 그대로 복사하고는 한다. 하지만 클린 코드 관점에서 중복 코드는 좋지 않은 코드이기 때문에 이 경우엔 공용으로 사용할 수 있는 생성자를 작성하는 편이 낫다.
다른 생성자를 호출하여 초기화 과정의 일부를 위임
공통으로 사용하는 생성자를 다른 생성자에서 호출하여 변수에 대한 중복 초기화 코드를 제거해 줄 뿐 아니라 베이스 클래스의 생성자가 반복적으로 호출되는 것도 막아준다.
다른 생성자를 호출하여 초기화 과정의 일부를 위임 + 기본 매개변수 기능
C# 4.0에 추가된 기본 매개변수 기능을 사용하면 생성자 내의 중복코드를 더욱 줄일 수 있다. MyClass 내에 있는 여러 개의 생성자를 기본값을 가진 매개변수를 취하는 생성자 하나로 대체할 수 있다.
여러 개의 생성자를 작성하는 대신 위와 같이 기본값을 갖는 매개변수를 취하는 생성자를 작성할 때는 몇 가지 트레이드오프(trade-off)를 고려해야 한다. 우선 코드의 구조를 단순화할 수 있고 코드의 양도 대폭 줄일 수 있다.
생성자를 정의할 때 기본값을 갖는 매개변수를 사용하는 방법은 널리 사용되는 방식이지만 일부 API는 리플렉션을 이용해서 객체를 생성하기 때문에 매개변수가 없는 생성자가 반드시 필요하다. 이 경우에는 임의의 생성자가 동일 클래스 내에 정의된 다른 생성자를 호출하는 방식인 생성자 체인 기법을 사용하는 것이 좋다.
생성자 공통 사용 코드를 다른 메서드로 분리
이외에도 여러 생성자에서 공통으로 사용하는 코드를 다른 메서드로 분리하는 방법이 있는데 일부 비효율적인 측면이 있다.
이 코드는 컴파일할 때 사용자가 작성하지 않은 코드를 추가한다. 우선 모든 인스턴스 변수에 대한 초기화 코드가 추가되고 이후에 베이스 클래스의 생성자를 호출하는 코드가 추가된다. 마지막으로, 사용자가 작성한 공용 유틸리티 함수를 호출하는 코드가 포함된다.
다음 코드는 컴파일러가 생성한 IL코드를 C#코드로 변경한 예이다.
이번 아이템의 첫 번째 예에 대해서도 컴파일러가 생성한 IL코드를 C# 코드로 변경한 예는 다음과 같다.
두 코드의 차이는 베이스 클래스의 생성자를 호출하는 코드와 인스턴스 변수를 초기화하는 코드가 모든 생성자에 모두 포함되지는 않는다는 것이다. 마지막으로 호출되는 생성자에서만 베이스 클래스의 생성자가 호출된다는 점도 중요하다.
특정 타입의 인스턴스가 생성되는 전체 순서
정적 변수의 저장 공간을 0으로 초기화
정적 변수에 대한 초기화 구문 수행
베이스 클래스의 정적 생성자 수행
정적 생성자 수행
인스턴스 변수의 저장 공간을 0으로 초기화
인스턴스 변수에 대한 초기화 구문 수행
적절한 베이스 클래스의 인스턴스 생성자 수행
인스턴스 생성자 수행
클래스 자체에 대한 초기화 작업은 단 한 번만 이뤄지기 때문에 동일한 타입으로 추가 인스턴스를 생성하면 5단계에서 부터 다시 수행된다.
정리
생성자를 작성할 때 고려해야할 부분은 멤버들을 원하는 값으로 초기화할 때 가능한 한 한 번만 초기화가 이뤄지도록 해야 한다는 것이다. 이를 위해서 단순한 초기화 작업이라면 멤버 초기화 구문을 사용하고 복잡한 초기화 과정이 필요할 때만 생성자를 사용하는 것도 좋은 방법이다. 그리고 생성자를 사용하게 된다면 코드의 중복을 피하기 위해서 공통적인 초기화 작업을 수행하는 공용 생성자를 작성하고 각 생성자가 이 생성자를 이용하도록 하는 것이 좋다.
오늘은 내용도 길고 여러 생성자를 다루는 작업을 별로 해보지 않아 익숙치 않아서 다소 어려웠다.
완전히 잊어버리지는 말고 나중에 여러 생성자를 작성할 일이 생기면 이 게시글로 다시 돌아와 보겠다.
참조 - Effective C# <강력한 C# 코드를 구현하는 50가지 전략과 기법, 이펙티브>, 빌 와그너, 김명신, 한빛미디어
'Programming > Effective C#' 카테고리의 다른 글
[Effective C# Item 16] 생성자 내에서는 절대로 가상 함수를 호출하지 마라 (0) | 2020.10.18 |
---|---|
[Effective C# Item 15] 불필요한 객체를 만들지 말라 (0) | 2020.10.18 |
[Effective C# Item 13] 정적 클래스 멤버를 올바르게 초기화하라 (0) | 2020.10.18 |
[Effective C# Item 12] 할당 구문보다 멤버 초기화 구문이 좋다 (0) | 2020.10.18 |
[Effective C# Item 11] .NET 리소스 관리에 대한 이해 (0) | 2020.10.18 |