Pregunta

He oído/leído el término pero no entiendo muy bien lo que significa.

Cuándo debería usar esta técnica y cómo puedo usarlo?¿Alguien puede proporcionar un buen ejemplo de código?

¿Fue útil?

Solución

El visitante patrón es una manera de hacer doble-envío en un objeto-orientado.

Es útil para cuando usted quiere elegir el método a utilizar para un determinado argumento basado en su tipo en tiempo de ejecución en lugar de tiempo de compilación.

Doble de despacho es un caso especial de varios de envío.

Cuando se llama a un método virtual de un objeto, que se considera único despacho debido a que el método se llama depende del tipo de objeto único.

Para el doble de despacho, tanto en el tipo de objeto y el método único argumento del tipo es tomado en cuenta.Esto es como la sobrecarga del método de resolución, salvo que el tipo de argumento se determina en tiempo de ejecución en doble-despacho, en lugar de estática en tiempo de compilación.

En varios de despacho, un método puede tener múltiples argumentos que se le pasa y la aplicación que se utiliza depende de cada uno de los argumentos del tipo.El orden en que los tipos son evaluados depende del lenguaje.En LISP, comprueba cada tipo de la primera a la última.

Idiomas con múltiples despacho de hacer uso de las funciones genéricas, que son sólo función de delcarations y no son como los métodos genéricos, que el uso de parámetros de tipo.

Hacer doble-despacho en C#, puede declarar un método con un único argumento de objeto y, a continuación, los métodos específicos con determinados tipos:

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).
    }
}       

Otros consejos

Bueno chicos, el código publicado por la Marca no es completa y lo que nunca hay no es de trabajo.

Tan ajustado y completo.

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();
    }
}

Gracias Marcos y otros para agradable explicación en Doble Despachador patrón

C# 4 presenta el pseudo tipo dynamic que resuelve la llamada a la función en tiempo de ejecución (en lugar de en tiempo de compilación).(Es decir, el tipo en tiempo de ejecución de la expresión se utiliza).Haga doble (o múltiple-dispatch) se puede simplificar a:

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"
}

Nota también mediante el uso de dynamic evitar que el analizador estático de que el compilador para examinar esta parte del código.Por lo tanto, debe considerar cuidadosamente el uso de dynamic.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top