문제

나는 그 용어를 듣거나 읽었지만 그것이 무엇을 의미하는지 잘 이해하지 못합니다.

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

도움이 되었습니까?

해결책

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

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

이중 파견은 특별한 경우입니다. 다중 파견.

객체에 대해 가상 메서드를 호출하면 호출되는 실제 메서드가 단일 객체의 유형에 따라 달라지므로 단일 디스패치로 간주됩니다.

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

다중 디스패치에서는 메서드에 여러 인수가 전달될 수 있으며 사용되는 구현은 각 인수의 유형에 따라 다릅니다.유형이 평가되는 순서는 언어에 따라 다릅니다.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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top