본문 바로가기
C#/Effective C#

[Effective C#] Item 23 타입 매개변수에 대해 메서드 제약 조건을 설정하려면 델리게이트를 활용하라1

by 코모's 2022. 10. 11.
반응형

언뜻 보면 C#에서 제약 조건을 설정하느 방법에는 한계가 많은 것 같다. 베이스 클래스 타입이나 특정 인터페이스로 제약 조건을 설정하거나, class 타입이나 struct 타입으로 형태를 제한하거나, 매개변수가 없는 생성자를 가져야 한다는 조건 정도를 설정하는게 끝인 것 같다.

임의 static 메서드를 반드시 구현해야 한다거나 매개변수를 취하는 생성자를 반드시 구현하도록 제약 조건을 설정할 수는 없다. 제한적이지만 인터페이스를 통해서 제약 조건을 설정할 수는 있지만 추가적으로 해야 할 작업이 너무 많고 기본적인 구조도 해칠 수 있다.

 

이를 위해서 메서드의 원형에 부합하는 델리게이트를 작성하는 것이 좋다.

 

인터페이스를 이용한 메서드 제약

 

어떤 제네릭 클래스에 대해 타입 매개변수 T가 반드시 Add() 메서드를 가져야 한다는 제약 조건을 설정하고 싶다고 해보자.

 

우선, Add() 메서드를 정의하는 IAdd<T> 인터페이스를 생성한다. 그리고 이 인터페이스를 구현한 클래스를 생성해야 하고 IAdd<T>가 정의한 Add() 메서드를 구현해야 한다. 이후 제네릭 클래스의 정의를 이용하여 닫힌 제네릭 클래스를 만들어야 한다. Add() 메서드 하나를 호출하기 위해 너무 많은 작업을 한다고 생각하지 않은가?

 

델리게이트를 이용한 메서드 제약

 

다행스롭게도 우리에겐델리게이트가 있다. 제약 조건으로 설정하고 싶은 메서드의 원형에 부합하는 델리테이트를 작성하면 된다.

 

특정 제네릭 클래스가 T타입의 두 객체를 더하는 메서드를 필요로 한다고 가정하자. 그럴 경우 다음과 같이 Add메서드를 구현할 수 있다.

public static class Example 
{
	public static T Add<T>(T left, T right, Func<T, T, T> AddFunc)
		=> AddFunc(left, right); 
}

이클래스 사용자는 람다 표현식을 이용하여 제네릭 클래스가 호출할 AddFunc 메서드를 정의하면 된다. Add를 호출하는 코드는 다음과 같다.

int a = 6; int b = 7; int sum = Example.Add(a, b, (x, y) => x + y);

다시한번 델리게이트를 이용하여 제약 조건을 설정하는 방법을 살펴보자.

 

1. 우선 적절한 메서드의 원형을 고안하고 이를 델리게이트 타입으로 정의한다.

2. 델리게이트의 인스턴스를 제네릭 메서드의 매개변수로 추가한다.

3. 람다 표현식을 인자로 전달하면 된다.

 

 

정리

설계의 특성을 드러내는 가장 좋은 방법은 class나 인터페이스로 제약 조건을 설정하는 것이다.

하지만, 제네릭 클래스나 제네릭 메서드 하나를 사용하기 위해서 인터페이스를 구현한 타입을 매번 새롭게 만드는 것은 매우 번거롭다.

델리테이트를 이용하면 제네릭 타입을 더 쉽게 작성할 수 있고 사용하기 편하다.

 

 

 

참조 - Effective C# <강력한 C# 코드를 구현하는 50가지 전략과 기법, 이펙티브>, 빌 와그너, 김명신, 한빛미디어

반응형