7

对于使用 Java 和 C# 等静态类型语言进行编码的人来说,单次分派问题最为熟悉。基本思想是:

而运行时多态性允许我们根据 的类型(运行时类型)调度到正确的方法调用receiver,例如:

IAnimal mything = new Cat();
mything.chop();

方法调用会根据 的运行时类型进行mything,即Cat. 这是单一的分派能力(存在于 Java/C# 中)。

现在,如果您不仅需要在接收器的运行时类型上进行分派,而且还需要在(多个)参数的类型上进行分派,那么您将面临一个小问题:

public class MyAcceptor {  
    public void accept (IVisitor vst) {...}   
    public void accept (EnhancedConcreteVisitor vst) {...}  
}

第二种方法永远不会被调用,因为在我们的“消费者”代码中,我们只是倾向于通过它们共同的超类型或接口来处理不同类型的对象(在我的示例中是访问者)。

这就是我问的原因——因为动态类型允许多重分派多态性,而 C# 4.0 具有动态关键字;)

4

2 回答 2

12

是的,动态类型允许多次分派——不,您不必创建自己的动态对象来执行此操作。

假设我们想要实现Enumerable.Count()自己,并且我们不想if (source is IList)在我们的代码中加载大量的“”测试。我们可以这样写:

public static class Enumerable
{
    public static int Count<T>(this IEnumerable<T> source)
    {
        dynamic d = source;
        return CountImpl(d);
    }

    private static int CountImpl<T>(ICollection<T> collection)
    {
        return collection.Count;
    }

    private static int CountImpl(ICollection collection)
    {
        return collection.Count;
    }

    private static int CountImpl<T>(string text)
    {
        return text.Length;
    }

    private static int CountImpl<T>(IEnumerable<T> source)
    {
        // Fallback
        int count = 0;
        foreach (T t in source)
        {
            count++;
        }
        return count;
    }
}

我并不是说这是一个好主意,但这就是它的工作方式:)

请注意,您需要注意不要引入可能最终导致对某些类型的模糊调用的情况。使用类作为参数这不是问题,但考虑到单个类可以实现多个接口。

于 2010-05-02T07:17:40.877 回答
1

是的,您可以创建执行任意复杂调度的 DLR 类型。查看http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx

于 2010-05-02T06:01:24.317 回答