【问题标题】:Single/double dispatch via "dynamic overload" in C#通过 C# 中的“动态重载”进行单/双调度
【发布时间】:2014-10-01 20:12:18
【问题描述】:

为什么 C# 本身不支持通过基于参数类型的“动态重载”进行双重分派?我看到这需要动态调度,但由于虚拟方法调用也是动态调度的,这对语言来说并不奇怪。那么为什么这个特性不是 C# 的一部分呢?使用反射实现此功能的最优雅的解决方案是什么(也许有一些库)?

class Program
{
    static void Main(string[] args)
    {
        var objs = new object[] { new Class1(), new Class2() };
        foreach (var item in objs)
        {
            Method(item);
        }
    }

    static void Method(Class1 obj)
    {
    }

    static void Method(Class2 obj)
    {
    }
}

class Class1
{
}

class Class2
{
}

UPDATE 确实,因为在这个例子中Method 不是虚拟的,并且只接受一个参数,这仍然是单次调度,但调度的“基数”在这个问题中并不那么重要,因为只要 > 0。

【问题讨论】:

  • 在 C#/C++ 和 Java 中通过模板/泛型至少可以使用某种形式的参数多态性。

标签: c# .net parametric-polymorphism


【解决方案1】:

virtual 用于单次调度。如果您需要双重调度,您可以在 C# 中执行此操作:

var objs = new object[] { new Class1(), new Class2() };
foreach (var item in objs)
{
    Method((dynamic)item);
}

这将使编译器以非常不同的方式解释对您的方法的调用。它将发出一个所谓的调用站点,它将在运行时确定应该调用哪个方法。这也称为后期绑定

在这个具体的例子中,你仍然会得到单分派,但如果Method 是虚拟的,它就会是双分派。

这对于快速实现访问者模式非常方便,但要注意这会比经典的手动双分派慢。因此,您可能希望在对性能敏感的代码中使用旧的好方法。

【讨论】:

  • @Matías 在这个例子中,它在技术上是仍然单调度。但如果Method 是虚拟的,那将是双重调度。
  • 我认为正确的术语是参数多态性
  • 对,为问题添加了参数多态性标签。
【解决方案2】:

为什么 C# 本身不支持通过基于参数类型的“动态重载”进行双重分派?

通过dynamic typing:

static void Main(string[] args)
{
    var objs = new object[] { new Class1(), new Class2() };
    // Note the change of type for item to "dynamic"
    foreach (dynamic item in objs)
    {
        Method(item);
    }
}

涉及编译时类型为dynamic 的值的操作是后期绑定的——因此重载决议是在执行时根据值的实际 类型执行的。当然,动态类型不仅仅是重载解析,还包括能够通过代码动态提供成员的类型。

所有这些都会影响性能 - 但有时这是最干净的方法。

您可能希望添加一个带有object 类型参数的额外重载作为“包罗万象”,以防某个值与其他任何一个重载都不匹配...尽管如果您的数组包含一个空元素。

【讨论】:

  • 我不确定我是否理解这种方法。你的意思是Method 将被调用两次,一次用于Method(Class1)Method(Class2)
  • @MatíasFidemraizer:是的,没错。它将根据值的执行时间类型选择要调用的重载。
  • 嗯,我明白了。我误解了调用Method ONCE ... 并解决这两个重载的双重厌恶。没关系,我疯了:D
【解决方案3】:

如果您真的感兴趣,.Net CLR 泛型的设计者之一 Andrew Kennedy 写了一篇关于此的文章。

http://research.microsoft.com/pubs/64039/transposingftocsharp.pdf

由于具有真正参数化多态性的 F# 使用相同的公共语言运行时,因此 C# 也可以实现它,并且决定是保留 C++/C# 语言风格之一。

来自他的文章:“同样,多态虚拟方法 [10] 的 CLR 实现涉及执行时代码生成,与足以支持非虚拟多态方法的加载时代码生成形成对比。”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    相关资源
    最近更新 更多