ITEM 19 :: EFFECTIVE C#


안녕하세요, 19번째 시간입니다. 점점 어려운 개념들이 나오기 시작하는 시점입니다.


이번 챕터는 런타임에 타입을 확인하여 최적의 알고리즘을 사용하라, 입니다. 이 역시 챕터 3, 제네릭 활용 챕터에 속해있는 내용인데요. 그리 긴 내용은 아니지만 이전 챕터에 대한 지식과, 런타임, 컴파일타임과 같은 전문지식을 어느정도 알고 있어야 이해가 쉬운 내용입니다. 물론 저는 알고 있음에도 이해가 쉽지만은 않은 내용이지만, 힘내보겠습니다!

설명

이는 제네릭활용에 관한 내용이다.

먼저, 제네릭을 사용함에 있어 생각해야할 점이 있다. 제네릭을 사용하게 되면, 제약조건의 사용 유무에 따라 런타임에 타입확인 유무가 결정된다. 앞서의 내용에서는 런타임에 타입확인을 하는 것보다, 컴파일 타임에 컴파일러가 타입 확인을 하는 것이 좋다고 했었다. 그리고 그게 제네릭을 사용하는 첫 번째 이유이기도 하다. 하지만, 그렇다고 무턱대고 제네릭을 사용하는 것이 좋은 결과를 불러오는 것은 아닌 모양이다. (또한 런타임에 타입을 확인할 경우, 런타임 환경을 최대한 고려하여 최적화된 타입별 생성자/메소드 오버로드등을 작성하는 것이 좋다.)

제네릭을 사용하게 되면 사용하는 곳에 따라 코드를 대폭 줄일 수 있지만, 다양한 상황에 대한 디테일한 C#코드를 작성할 수 없고, 개별 타입에 대한 세세한 대응이 불가능하다. 그 말인 즉슨, 코드의 유연성이 떨어진다는 것이다.

따라서, 그 상황을 판단하여, 제네릭을 사용하면 더 좋을 때와, 사용하지 않아도 될 때를 잘 구별해야만 한다.

사실, 이 부분에 대해서는 필자가 구별하기란 쉽지 않아 책의 내용을 필자 나름대로 해석한 부분이 없지않아 있으므로, 틀린 부분이나 수정해야할 부분이 있다면 댓글로 피드백을 해주길 바란다. (너무 공격적이게만 하지 않아줬으면 한다. 필자도 사람이다.)

먼저, 제네릭을 사용할 때 가장 좋은 조건에 대해서는 책을 참고하면

  1. 반복적인 소스코드가 들어있거나,

  2. 각각 개별 타입에 대한 고유한 특성을 고려하고, 그 특화된 기능들을 살릴 수 있는 경우이거나,

  3. 타입에 따라 내부 기능에 이상이 없는 경우이면서,

  4. 다양한 상황에 대처할 필요가 없을 경우(다양한 상황에 대한 디테일한 C#코드 작성에 관한 부분이다.)

이 정도가 된다. 그리고 당연하게도 이 반대에 해당하는 경우에는 제네릭을 사용하지 않는 편이 좋다.

특히나 2번의 경우 단순한 값타입이라면 문제될 것이 없지만 참조타입의 경우 해당 클래스의 객체가 어떤 함수를 가지고 있는지부터 해서 많은 정보가 필요하기 때문에 그 고유한 특성을 고려하면서 특화된 기능을 살리는 것은 쉬운 일이 아니므로 많은 고민이 필요한 부분이다.

위와같은 상황에 제네릭을 잘 작성할 수 있다면,

그 제네릭은 재사용성이 높으면서, 개별 타입에 최적화된 코드를 작성할 수 있다는 말이며, 이는 코드의 간소화에도 큰 영향을 줄 수 있다! 이 부분에 대해서는 필자 생각엔, 제네릭을 많이 써봐야 알 수 있을 것 같다. 그것도 엄청나게 많은 타입별로 말이다. 다만, 그럴 일이 아직은 없어서, 일단 이렇다는 것만 생각하고 넘어가야겠다. C++에서 STL도 그렇지만 이쪽은 파면 팔수록 깊은 구덩이인 것 같다.