【问题标题】:Why isn't the overloaded method getting called?为什么不调用重载方法?
【发布时间】:2013-04-12 16:19:42
【问题描述】:

我认为被调用的方法是确定的运行时,还是我错过了什么?示例代码:

class Program
{
    static void Main(string[] args)
    {
        var magic = new MagicClass();
        magic.DoStuff(new ImplA());
        magic.DoStuff(new ImplB());
        Console.ReadLine();
    }
}
class MagicClass
{
    internal void DoStuff<T>(T input) where T : SomeBase
    {
        HiThere(input);
    }

    void HiThere(SomeBase input)
    {
        Console.WriteLine("Base impl");
    }

    void HiThere(ImplA input)
    {
        Console.WriteLine("ImplA");
    }

    void HiThere(ImplB input)
    {
        Console.WriteLine("ImplB");
    }
}

abstract class SomeBase
{

}
class ImplA : SomeBase{}
class ImplB : SomeBase{}

我以为我会得到:

ImplA
ImplB

作为输出,但它打印Base impl。我有什么办法可以在不强制转换输入的情况下获得重载方法?

【问题讨论】:

标签: c# .net


【解决方案1】:

重载由编译器选择。在这里打电话:

internal void DoStuff<T>(T input) where T : SomeBase
{
    HiThere(input);
}

它选择带有SomeBase 的那个,因为这就是它在编译时的全部内容。

您最可能想要的是覆盖。这意味着必须将不同的逻辑放入 SomeBase 的继承者中:

abstract class SomeBase
{
  abstract string Name { get; }
}
class ImplA : SomeBase{ override string Name { get { return "ImplA"; } } }
class ImplB : SomeBase{ override string Name { get { return "ImplB"; } } }

void HiThere(SomeBase input)
{
    Console.WriteLine(input.Name);
}

【讨论】:

  • 另一种可能是他想做double dispatch或者使用visitor pattern
  • 或者使用dynamic:HiThere((dynamic)input); 这将重载决议移动到input的确切类型已知的运行时。
  • @DanielHilgarth:这可能是双向调度的最佳实现。 :)
  • @MatthewWatson:确实,这将是双重调度的具体实现。
【解决方案2】:

在编译期间选择重载。
在运行时选择覆盖。

在这里,编译器只知道 T 可以分配给SomeBase,而没有别的。实际上,如果它按您的预期工作,您将能够完全跳过where T : SomeBase 部分。您需要它的原因是编译器需要知道该信息才能检查可以在提供的对象上调用什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 2012-03-11
    • 2021-03-20
    • 2017-09-29
    • 2015-07-01
    • 2018-03-26
    相关资源
    最近更新 更多