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

참조

소개

  • 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
  • 다시 위의 내용을 순서대로 정리해 보도록 하겠습니다.
    1. 우선 적절한 메서드의 원형을 고안하고 이를 델리게이트 타입(Action, Func, Predicate) 타입으로 정의합니다.
    2. 델리게이트의 인스턴스를 제네릭 메서드의 매개변수로 추가합니다.
    3. 람다 표현식을 인자로 전달하면 됩니다.

정리

  • 설계의 특성을 드러내는 가장 좋은 방법은 class나 인터페이스로 제약 조건을 설정하는 것입니다.
  • 하지만, 제네틱 클래스나 제네릭 메서드 하나를 사용하기 위해서는 인터페이스를 구현한 타입을 매번 새롭게 정의하고 만드는것은 번거로운 작업입니다.
  • 때문에, 델리게이트를 이용하면 제네릭 타입을 더 쉽게 작성할 수 있고 사용하기 편하다는 장점이 있습니다.
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY