티스토리 뷰
[Effective C# Item 19] 런타임에 타입을 확인하여 최적의 알고리즘을 사용하라
weekyear 2020. 10. 18. 14:24[Effective C# Item 19]
런타임에 타입을 확인하여 최적의 알고리즘을 사용하라
제네릭을 활용하면 코드를 덜 작성해도 되기 때문에 매우 유용하지만 타입이나 메서드를 제네릭화하면 구체적인 타입이 주는 장점을 잃고 타입의 세부적인 특징을 고려한 최적화한 알고리즘도 사용할 수 없다.
그래서 만약 어떤 알고리즘이 특정 타입에 대해 더 효율적으로 동작한다고 생각된다면 그냥 그 타입을 이용하도록 작성하는 것도 좋다. 직전 Item 때 처럼 제약 조건을 설정하는 방법도 있지만 제약 조건이 항상 능사는 아니다.
특정 타입의 시퀀스를 역순으로 순회하기 위해서 다음과 같이 클래스를 만들었다.
위 코드는 잘 동작하는 편이고 랜덤 액세스를 지원하지 않는 컬렉션에 대해서 개별 요소를 역순으로 순회하기 위한 유일한 방법이기도 하다. 하지만 대부분의 컬렉션들이 랜덤 액세스를 지원하기 때문에 이와 같은 코드는 매우 비효율적이다.
생성자로 전달한 인자가 IList<T>를 지원한다면 이처럼 복제본을 만들 이유가 없다. IEnumerable<T>를 구현하고 있는 대부분의 타입들이 IList<T> 또한 구현한다는 사실에 착안하여 코드를 좀 더 효율적으로 개선해보자.
그리고 매개변수가 IList<T> 타입인 것을 컴파일타임에 알 수 있는 생성자를 하나 더 추가할 수도 있다.
이제 IList<T>를 사용하면 IEnumerable<T>만을 사용할 때보다 더 효율적으로 동작하도록 개선할 수 있다. 하지만 IList<T>를 구현하지 않고 ICollection<T>만을 구현한 컬렉션들에 대해서는 여전히 비효율적으로 동작한다.
GetEnumerator()를 살펴보면 입력 시퀀스가 ICollection<T>만을 구현한 경우 입력 시퀀스에 대한 복제본을 생성해야 하므로 매우 느리게 동작할 수밖에 없다. 따라서 런타임 중에 타입을 확인하고 ICollection<T>가 제공하는 Count 속성을 활용하여 저장소 공간을 미리 초기화하도록 코드를 조금 개선할 수 있다.
마치기 전에
ReverseEnumerable<T>내에서 수행되는 매개변수에 대한 테스트는 모두 런타임에 이뤄진다. 즉 추가 기능을 확인하는 과정도 일정 부분 비용이 발생하지만 대부분의 경우에는 이 비용은 모든 요소를 복사하는 것에 비해 훨씬 적다.
정리
타입에 대한 제약 조건을 거의 사용하지 않으면서도 타입 매개변수로 지정될 가능성이 있는 타입들의 고유한 특성을 고려하고 특화된 기능들을 최대한 활용하여 제네릭 타입을 만드는 방법을 살펴봤다.
이와 같이 코드를 작성하면 재사용성이 높으면서도 개별 타입에 최적화된 코드 작성이 가능하다.
솔직히 말하면 이 챕터에 대한 이해도가 50퍼센트 밖에 되지 않는다.
아직 내가 C# 전반에 대한 기초 지식이 탄탄하지 않다는 의미라고 생각한다.
일단 지금은 억지로나마 책을 다 떼는 데 목적으로 두고 나중에 다시 돌아와 이 책을 볼 것을 맹세한다.
참조 - Effective C# <강력한 C# 코드를 구현하는 50가지 전략과 기법, 이펙티브>, 빌 와그너, 김명신, 한빛미디어
'Programming > Effective C#' 카테고리의 다른 글
[Effective C# Item 21] 타입 매개변수가 IDisposable을 구현한 경우를 대비하여 제네릭 클래스를 작성하라 (0) | 2020.10.18 |
---|---|
[Effective C# Item 20] IComparable<T>와 IComparer<T>를 이용하여 객체의 선후 관계를 정의하라 (0) | 2020.10.18 |
[Effective C# Item 18] 반드시 필요한 제약 조건만 설정하라 (0) | 2020.10.18 |
[Effective C# Item 17] 표준 Dispose 패턴을 구현하라 (0) | 2020.10.18 |
[Effective C# Item 16] 생성자 내에서는 절대로 가상 함수를 호출하지 마라 (0) | 2020.10.18 |