프로그램을 개발하다 보면 List<T>나 Dictionary<T>와 같이 제네릭 컬렉션에 타입 매개변수를 지정하여 사용하게 될 것이다. 기존에 사용 중인 컬렉션타입에 영향을주지 않으면서 새로운 기능을 추가하고 싶다면 구체화된 컬렉션 타입에 대해 확장 메서드를작성하면 된다.
예시 : IEnumerable<int>
이번에도 IEnumerable에 이미 구현된예시가 있다.
타입 매개변수로 특정 숫자 타입이 전달 되었을 경우에만 사용할 수 있는 확장 메서드들이 있다.
public static class Enumerable
{
public static int Average(this IEnumerable<int> sequence);
public static int Max(this IEnumerable<int> sequence);
public static int Min(this IEnumerable<int> sequence);
public static int Sum(this IEnumerable<int> sequence);
// 다른 메서드들은 생략
}
이 패턴은 타입 매개변수로 특정 타입이 주어질 대, 해당 타입에 대하여 가장 효과적으로 동작하도록 코드를 분리하여 구현하는 방법이다.
새로운 예시를 들어보자. 전자상거래 응용프로그램을 개발 중에 있으며 고객에게 쿠폰을 발송하는메서드를 만들어야하는 메서드와 지난 한 달간 아무런 주문도 하지 않은 고객을 찾는 메서드를 작성해보자. 다음과 같이 코드를 작성할 수 있다.
public static void SendEmailCoupons(this IEnumerable<Customer> customers, Coupon specialOffer);
public static IEnumerable<Customer> LostProspects(this IEnumerable<Customer> targetList);
확장메서드를 사용하지 않았다면 구체화된 제네릭 타입을 상속하여 새로운 타입을 만들어야 했을 것이다. 이 경우 다음과같은 코드가 작성되었을 것이다.
public class CustomerList : List<Customer>
{
public void SendEmailCoupons(Coupon specialOffer);
public static IEnumerable<Customer> LostProspects();
}
왜 확장 메서드를 사용하는 편이 이점이 많을까? 확장 메서드는 IEnumerable<Customer>를 기반으로 작성 되었고 파생 클래스를 새로 만드는 방식은 List<Customer>를 기반으로 한다. 따라서 새롭게 구성한 CustomerList에 대해서는 더이상 Iterator 메서드들을 사용할 수 없다.
그리고 확장 메서드들을 사용하면 람다 표현식을 이용하여 재사용 가능한 쿼리를 작성할 수 있다. Where 절의 술어만ㅇ르 재사용하는 것이 아니라 전체 쿼리를 재사용할 수있다.
결론
구체화된 제네릭 타입을 상속하여 메서드를 추가하기 보다는 확장 메서드를 구현하는편이 훨씬 낫다. 이러한 방식을 사용하면 단순한 기능을 제공하는 메서드를 다양하게 재사용할 수 있는 길이열린다. 게다가 컬렉션 고유의 저장소 모델과 무관하게 기능을 구현할 수 있다.
참조 - Effective C# <강력한 C# 코드를 구현하는 50가지 전략과 기법, 이펙티브>, 빌 와그너, 김명신, 한빛미디어
'C# > Effective C#' 카테고리의 다른 글
[Effective C#] Item 30 루프보다 쿼리 구문이 낫다. (0) | 2022.11.07 |
---|---|
[Effective C#] Item 29 컬렉션을 반환하기보다 이터레이터를 반환하는 것이 낫다. (0) | 2022.11.07 |
[Effective C#] Item27 인터페이스는 간략히 정의하고 기능의 확장은 확장 메서드를 사용하라. (0) | 2022.10.26 |
[Effective C#] Item26 제네릭 인터페이스와 논 제네릭 인터페이스를 함께 구현하라 (0) | 2022.10.26 |
[Effective C#] Item 25 타입 매개변수로 인스턴스 필드를 만들 필요가 없다면 제네릭 메서드를 정의하라 (0) | 2022.10.25 |