基于编译时类型的运行时类型的调用方法

Mer*_*ovi 5 .net c# polymorphism

在一个应用程序中,我需要.NET基于其运行时类型而不是其编译时类型来调用方法.

简化示例:

    class A { }

    class B : A { }

    static void Main(string[] args)
    {
        A b = new B();
        Print(b);
    }

    static void Print(A a)
    {
        Console.WriteLine("Called from A");
    }

    static void Print(B b)
    {
        Console.WriteLine("Called from B");
    }
Run Code Online (Sandbox Code Playgroud)

上面的代码实际上会打印Called from A,但我需要它Called from B.

这按预期工作:

static void Print(A a)
{
    var b = a as B;
    if (b != null)
       return Print(b);
    else
       Console.WriteLine("Called from A");
}
Run Code Online (Sandbox Code Playgroud)

但出于可维护性的考虑,这是不可取的.

我相信这个问题与此类似:为什么不根据对象的运行时类型选择此方法?,但对于.NET而不是Java.

Jon*_*eet 10

如果您使用的是.NET 4或更高版本,最简单的方法是使用动态类型:

dynamic b = new B();
Print(b);
Run Code Online (Sandbox Code Playgroud)

几乎所有使用类型值的表达式dynamic都将被动态调用,"mini-C#编译器"在执行时应用与编译时相同的规则,但使用这些动态值的实际执行时类型.(类型在编译时静态已知的表达式仍将被视为具有这些类型 - 它不会使重载决策的所有内容变为动态.)

如果你不使用.NET 4,那就更难了 - 你既可以使用反射,也可以硬编码选项,这两种选择都不是很有趣.


Dan*_*rth 5

您可以使用以下dynamic类型:

A b = new B();
dynamic tmp = b;
Print(tmp); // Prints "Called from B"
Run Code Online (Sandbox Code Playgroud)

但请注意,如果没有匹配的方法,它会产生运行时异常而不是编译错误.