Шаблон посетителя - это способ выполнить двойную диспетчеризацию объектно-ориентированным способом.
Это полезно, когда вы хотите выбрать, какой метод использовать для данного аргумента, основываясь на его типе во время выполнения, а не во время компиляции.
Двойная отправка - это особый случай многократная отправка .
Когда вы вызываете виртуальный метод для объекта, это считается единой диспетчеризацией, потому что какой фактический метод вызывается, зависит от типа отдельного объекта.
Для двойной диспетчеризации учитывается как тип объекта, так и тип единственного аргумента метода. Это похоже на разрешение перегрузки метода, за исключением того, что тип аргумента определяется во время выполнения в двойной диспетчеризации, а не статически во время компиляции.
В режиме множественной диспетчеризации методу может быть передано несколько аргументов, и какая реализация используется, зависит от типа каждого аргумента. Порядок оценки типов зависит от языка. В 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).
}
}