참조
- https://docs.microsoft.com/ko-kr/dotnet/csharp/fundamentals/types/generics
- https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
소개
- C# 제네릭에서 제약 조건을 설정하는 방법은 한계가 많은 것처럼 보입니다.
- 베이스 클래스 타입이나 특정 인터페이스로 제약 조건을 설정하거나, class 타입, struct 타입으로 형태를 제한 혹은 매개변수가 없는 생성자를 가져야 한다는 조건정도를 설정할 수 있는게 다입니다.
- 임의의 static 메서드를 반드시 구현해야 한다거나 매개변수를 취하는 생성자를 반드시 구현하도록 제약 조건을 설정할 수는 없습니다.
- 제한적이지만 인터페이스를 통해서 제약 조건을 설정할 수는 있지만 추가적으로 해야 할 작업이 너무 많고 기본적인 구조도 해칠 수 있습니다.
- 이를 위해 메서드의 원형에 부합하는 델리게이트 를 작성하는 것이 좋습니다.
인터페이스를 이용한 메서드 제약
- 어떤 제네릭 클래스에 대해 타입 매개변수 T가 반드시 Add() 메서드를 가져야 한다는 제약 조건을 설정하고 싶다고 가정해 봅니다.
- 우선, Add() 메서드를 정의하는 IAdd<T> 인터페이스를 생성합니다.
- 그리고 이 인터페이스를 구현한 클래스를 생성해야하고 IAdd<T> 가 정의한 Add() 메서드를 구현해야 합니다.
- 다음 제네릭 클래스의 정의를 이용하여 닫힌 제네릭 클래스를 만들어야 합니다.
- Add() 메서드 하나를 호출하기 위해서는 앞서 많은 작업이 필요하고 너무 복잡해 진다는 느낌이 듭니다.
델리게이트를 이용한 메서드 제약
- 앞서 복작한 인터페이스를 이용한 메서드 제약 대신, 델리게이트를 사용하면 보다 간단하게 메서드 제약을 사용할 수 있습니다.
- 제약 조건으로 설정하고 싶은 메서드의 원형에 부합하는 델리게이트를 작성하면 됩니다.
- 특정 제네릭 클래스 T 타입의 두 객체를 더하고 빼는 메서드를 필요한다고 가정해 봅니다.
- 다음과 같이 델리게이트를 이용하여 Add(), Minus() 메서드를 구현할 수 있습니다.
- Example 클래스의 사용자는 람다 표현식을 이용하여 제네릭 클래스가 호출할 AddFunc 메서드, MinusFunc 메서드 를 정의하면 됩니다.
using System;
namespace ConsoleApp7
{
class Program
{
static void Main(string[] args)
{
int left = 10;
int right = 20;
int sum = Example.Add(left, right, (left, right) => left + right);
int minus = Example.Minus(left, right, (left, right) => left - right);
Console.WriteLine($"Sum : {sum}");
Console.WriteLine($"Minus : {minus}");
}
}
public static class Example
{
public static T Add<T>(T left, T right, Func<T, T, T> AddFunc) =>
AddFunc(left, right);
public static T Minus<T>(T left, T right, Func<T, T, T> MinusFunc) =>
MinusFunc(left, right);
}
}
Sum : 30
Minus : -10
- 다시 위의 내용을 순서대로 정리해 보도록 하겠습니다.
- 우선 적절한 메서드의 원형을 고안하고 이를 델리게이트 타입(Action, Func, Predicate) 타입으로 정의합니다.
- 델리게이트의 인스턴스를 제네릭 메서드의 매개변수로 추가합니다.
- 람다 표현식을 인자로 전달하면 됩니다.
정리
- 설계의 특성을 드러내는 가장 좋은 방법은 class나 인터페이스로 제약 조건을 설정하는 것입니다.
- 하지만, 제네틱 클래스나 제네릭 메서드 하나를 사용하기 위해서는 인터페이스를 구현한 타입을 매번 새롭게 정의하고 만드는것은 번거로운 작업입니다.
- 때문에, 델리게이트를 이용하면 제네릭 타입을 더 쉽게 작성할 수 있고 사용하기 편하다는 장점이 있습니다.
728x90
'C# > Effective C# 책 정리' 카테고리의 다른 글
[Effective C# 개정판 3판] Item : 27장 인터페이스는 간략히 정의하고 기능의 확장은 확장 메서드를 사용하라 (0) | 2021.08.15 |
---|---|
[Effective C# 개정판 3판] 아이템 25: 타입 매개변수로 인스턴스 필드를 만들 필요가 없다면 제네릭 메서드를 정의하라 (0) | 2021.08.11 |
[Effective C# 21장] 타입 매개변수가 IDisposable을 구현한 경우를 대비하여 제네릭 클래스를 작성하라 (0) | 2021.07.14 |
[Effective C# 개정판 3판 19장] 런타임에 타입을 확인하여 최적의 알고리즘을 사용하라 (0) | 2021.06.11 |
[Effective C# 개정판 3판 ] 17장 표준 Dispose 패턴을 구현하라 (0) | 2021.06.03 |
이 글을 공유하기