
Effective C# Item 16
객체가 완전히 생성되기 이전에 가상 함수를 호출하면 이상 동작을 일으킨다. 어떤 타입이든 생성자가 수행을 완료할 때까지는 객체가 완전히 생성되었다고 할 수 없다. 따라서 생성자 내에서 가상 함수를 호출하면 예상처럼 동작하지 않는다.
class B { protected B() { VFunc(); } protected virtual void VFunc() { Console.WriteLine("VFunc in B"); } } class Derived : B { private readonly string msg = "Set by initalizer"; public Derived(string msg) { this.msg = msg; } protected override void VFunc() { Console.WriteLine(msg); } public static void Main() { var d = new Derived("Constructed in main"); } }무엇이 출력될까?
Main에서 Derived 클래스 객체 d를 생성한다.
Derived 클래스의 생성자는 부모 클래스인 B의 생성자를 호출한다. 이 때 VFunc()메서드가 호출된다.
다음으로 Derived 클래스의 생성자가 실행된다. 이 때 msg가 "Constructed in main"으로 초기화된다.Set by initailizer
결론
베이스 클래스의 생성자 내에서 가상 함수를 호출하면 파생 클래스가 가상 함수를 어떻게 구현했는지에 따라 매우 민감하게 동작하게 된다. 베이스 클래스의 생성자 내에서 가상 함수를 호출하게 되면 구조가 매우 취약한 코드가 돼버린다.