주녘공부일지

[C#] 대리자(delegate) vs 인터페이스(interface) 본문

Programming/Definition, Etc

[C#] 대리자(delegate) vs 인터페이스(interface)

주녘 2023. 11. 10. 20:50

대리자(delegate)와 인터페이스(interface)를 비교하기 위해 같은 기능을 하는 간단한 예제를 들고 후술

1) 대리자 (Delegate)

https://godgjwnsgur7.tistory.com/122

 

[C#] 대리자 (Delegate - Action, Func)

대리자 (Delegate) 어떤 메서드를 호출하는 방법을 담은 객체 - C의 함수 포인터 같은 지연 호출 수단 등과 같이 프로그래밍 언어에서 말하는 Callback과 유사 - 제네릭 대리자 형식으로 선언할 수도

godgjwnsgur7.tistory.com

 ex) 제네릭 형식에 제네릭 형식 매개변수를 둔 예시

public delegate T Transformer<T> (T arg);

public class Util
{
    public static void Transform<T> (T[] values, Transformer<T> t)
    {
        for(int i = 0; i < values.Length; i++)
            value[i] = t(values[i]);
    }
}

public Test
{
    static void Main()
    {
        int[] values = { 1, 2, 3 };
        Util.Transform {values, Square); // Square 변환 적용
        foreach(int i in values)
            Console.Write(i + "  "); // 1  4  9
    }
    
    static int Square(int x) => x * x;
}

2) 인터페이스 (Interface)

https://godgjwnsgur7.tistory.com/104

 

[C#] 인터페이스 ( interface )

1. 인터페이스의 상속 - 인터페이스는 다중 상속이 가능함 + 다중 상속으로 인해 인터페이스의 멤버이름이 충돌할 수 있는데, 이를 해소하는 방법 중 하나는 멤버를 명시적으로 구현하는 것임 (

godgjwnsgur7.tistory.com

 ex) 위 예제를 대리자 대신 인터페이스를 이용한 예시

public interface ITransformer
{
    int Transform(int x);
}

public class Util
{
    public static void TransformAll(int[] values, ITransformer t)
    {
        for(int i = 0; i < values.Length; i++)
            values[i] = t.Transform(values[i]);
    }
}

class Squarer : ITransformer
{
    public int Transform(int x) => x * x;
}

...

static void Main()
{
    int[] values = { 1, 2, 3 };
    Util.TransformAll(values, new Squarer());
    foreach(int i in values)
        Console.Write(i + "  "); // 1  4  9
}

대리자(Delegate) vs 인터페이스(Interface)

대리자로 해결이 가능한 문제는 인터페이스로도 해결할 수 있음

- 하지만, 인터페이스를 이용한 설계에서는 변환마다 개별적인 형식을 작성할 수 밖에 없기 때문에 비슷한 코드를 중복으로 작성해야 하는 등의 번거로운 작업이 필요해질 수 있음

 ex) 비슷한 코드를 중복으로 작성하는 예제

class Squarer : ITransformer
{
    public int Transform (int x) => x * x;
}

class Cuber : ITransformer
{
    public int Transform (int x) => x * x * x;
}

...

static void Main()
{
    int[] values = { 1, 2, 3 };
    Util.TransformAll (values, new Cuber());
    foreach(int i in values)
        Console.Write(i + "  "); // 1  8  27
}

즉, 다음 조건 중 하나 이상이 참이라면 인터페이스를 이용한 설계보다 대리자를 이용한 설계가 더 유리할 수 있으므로 고려해볼 필요가 있음

1) 인터페이스가 메서드를 하나만 정의

2) 다중 캐스팅 능력 필요

3) 구독자가 인터페이스를 여러 번 구현해야 함

 

 

참고도서) C# 6.0 완벽가이드