Programing

C #에서 이중 디스패치?

crosscheck 2020. 12. 2. 08:02
반응형

C #에서 이중 디스패치?


나는 그 용어를 들었거나 읽었지만 그것이 의미하는 바를 잘 이해하지 못합니다.

이 기술은 언제 사용해야하며 어떻게 사용해야합니까? 누구든지 좋은 코드 샘플을 제공 할 수 있습니까?


방문자 패턴은 객체 지향 방식으로 이중 디스패치를 ​​수행하는 방법입니다.

컴파일 타임이 아닌 런타임에 유형을 기반으로 주어진 인수에 사용할 메서드를 선택하려는 경우에 유용합니다.

이중 디스패치는 다중 디스패치 의 특수한 경우입니다 .

개체에서 가상 메서드를 호출 할 때 실제 메서드가 호출되는 것은 단일 개체의 유형에 따라 다르므로 단일 디스패치로 간주됩니다.

이중 디스패치의 경우 객체 유형과 메서드 단독 인수 유형이 모두 고려됩니다. 이것은 인수 유형이 컴파일 타임에 정적으로가 아닌 이중 디스패치로 런타임에 결정된다는 점을 제외하면 메서드 오버로드 해결과 유사합니다.

다중 디스패치에서 메서드는 여러 인수를 전달할 수 있으며 사용되는 구현은 각 인수의 유형에 따라 다릅니다. 유형이 평가되는 순서는 언어에 따라 다릅니다. LISP에서는 처음부터 마지막까지 각 유형을 확인합니다.

다중 디스패치를 ​​사용하는 언어는 일반 함수를 사용하는데, 이는 함수 설명 일 뿐이며 유형 매개 변수를 사용하는 일반 메서드와는 다릅니다.

C #에서 이중 디스패치를 ​​수행하려면 단독 개체 인수를 사용하여 메서드를 선언 한 다음 특정 형식을 사용하는 특정 메서드를 선언하면됩니다.

using System.Linq;  

class DoubleDispatch
{ 
    public T Foo<T>(object arg)
    { 
        var method = from m in GetType().GetMethods()
                   where    m.Name == "Foo" 
                         && m.GetParameters().Length==1
                         && arg.GetType().IsAssignableFrom
                                           (m.GetParameters()[0].GetType())
                         && m.ReturnType == typeof(T)
                   select m;

        return (T) method.Single().Invoke(this,new object[]{arg});          
    }

    public int Foo(int arg) { /* ... */ }

    static void Test() 
    { 
        object x = 5;
        Foo<int>(x); //should call Foo(int) via Foo<T>(object).
    }
}       

안녕 여러분, Mark가 게시 한 코드가 완전하지 않으며 작동하지 않습니다.

그래서 조정되고 완성되었습니다.

class DoubleDispatch
{
    public T Foo<T>(object arg)
    {
        var method = from m in GetType().GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic)
                     where m.Name == "Foo"
                           && m.GetParameters().Length == 1
                           //&& arg.GetType().IsAssignableFrom
                           //                  (m.GetParameters()[0].GetType())
                           &&Type.GetType(m.GetParameters()[0].ParameterType.FullName).IsAssignableFrom(arg.GetType())
                           && m.ReturnType == typeof(T)
                     select m;


        return (T)method.Single().Invoke(this, new object[] { arg });
    }

    public int Foo(int arg)
    {
        return 10;
    }

    public string Foo(string arg)
    {
        return 5.ToString();
    }

    public static void Main(string[] args)
    {
        object x = 5;
        DoubleDispatch dispatch = new DoubleDispatch();

        Console.WriteLine(dispatch.Foo<int>(x));


        Console.WriteLine(dispatch.Foo<string>(x.ToString()));

        Console.ReadLine();
    }
}

Double Dispatcher 패턴에 대한 좋은 설명에 대해 Mark와 다른 사람들에게 감사드립니다.


C # 4에서는 dynamic컴파일 타임 대신 런타임에 함수 호출을 해결 하는 의사 형식 도입했습니다 . (즉, 표현식의 런타임 유형이 사용됩니다.) 이중 (또는 다중 디스패치)는 다음과 같이 단순화 할 수 있습니다.

class C { }

static void Foo(C x) => Console.WriteLine(nameof(Foo));
static void Foo(object x) => Console.WriteLine(nameof(Object));

public static void Main(string[] args)
{
    object x = new C();

    Foo((dynamic)x); // prints: "Foo"
    Foo(x);          // prints: "Object"
}

또한 dynamic컴파일러의 정적 분석기를 사용 하여 코드의이 부분을 검사하지 못하도록합니다. 따라서 dynamic.

참고 URL : https://stackoverflow.com/questions/42587/double-dispatch-in-c

반응형