C#/이펙티브 C#

아이템16.생성자 내에서는 절대로 가상함수를 호출하지 마라.

공부를하자 2023. 7. 20. 01:51

-객체를 완전히 생성하기전에 가상함수(virtual) 호출하면 이상동작을 일으킨다.

-어떤 타입이든 생성자가 작업을 완료할떄까지 객체가 완전히 생성되었다고 없다.

-class B 생성자를 호출 할때 가상함수 VFunc 호출한다.

-class B 상속 받는 Derived 클래스는 생성자가 호출될 msg 쓰는 메서드를 호출한다.

-Vfunc  오버라이드 되어 런타임에 재정의한 함수가 발동한다.

-msg 변수는 'Set by intializer' 기본이고 main 객체가 만들어질 때는 'Constructed in main'

 쓰도록 작성되있다.

-그렇지만 쓰여지는 것은 'Set by intializer'이다.

-C#에서 생성자의 본문으로 진입하는 순간 해당 객체는 이미 초기화가 완료되었다고 간주하기에

 Derived의 생성자에서 msg가 this.msg = msg로 초기화되지 않은 상태에서 Derived.VFunc()가 수행된다.

 

- 코드는 class B 추상클래스 만들었다. 추상클래스는 객체를 만들 없고

 파생클래스인 Derived VFunc() 구현해야한다.

-그래서 C# 런타임에 타입 고려하여 VFunc() 호출하여 런타임 예외가 발생하지 않는다.

-하지만 가상함수처럼 의도치않은 오류가 있다.

-readonly 선언된 msg 값은 생성자가 완료될 떄까지 변경이 생길 있다.

-생성자가 수행중 일떈 멤버변수는 어떠한 값도 갖고 있지 않는 상태로 간주해야하는 것이 옳다.

 

결론:생성자 내에서는 절대로 가상함수를 호출하지 말자.