多态方法不适用于C#4

时间:2011-11-15 18:41:20

标签: c# c#-4.0 polymorphism

我偶然发现了一个非常有趣的问题。提供以下代码:

using System;

class Program
{
    class A { }
    class B : A { }

    private static void MyMethod(A a) /* first method */
    {
        Console.WriteLine("A"); ;
    }

    private static void MyMethod(B b) /* second method */
    {
        Console.WriteLine("B");
    }

    static void Main(string[] args)
    {
        var a = new A();
        // Call first method
        MyMethod(a);

        A b = new B();
        // Should call the second method
        MyMethod(b);

        Console.ReadLine();
    }
}

我希望第二种方法会被调用,因为变量的运行时类型是B.为什么代码会调用第一种方法呢?

谢谢, 提笔

一些澄清:多态性是指在声明方法时无关的几种形式。

方法重载是多态,ad-hoc多态的一种形式。

通常使用后期绑定实现多态的方式。

dynamic是此问题的解决方法。

事实是,这不适用于C#(或Java),这是一个设计上的决定,我想理解为什么会这样做,而且没有一个答案能回答这个问题。

/提笔

3 个答案:

答案 0 :(得分:14)

这根本不是多态的例子。当您在对象上调用方法时,而不是在将对象用作参数时,会发生多态性。这只是方法重载的一个简单示例。

您将b声明为类型A,因此编译器将链接到使用类型A的重载。链接器不关心B是A的子类,它只是选择具有最接近签名的重载传入的参数的声明类型(不是实际类型)。

如果你想强制它使用第二种方法,则在方法调用中将b转换为B类。

MyMethod((B)b);

答案 1 :(得分:6)

默认情况下,C#中的方法重载是在编译时静态确定的。由于您传递的是类型为A的静态类型变量,因此它将静态绑定到具有A重载的方法。使用dynamic关键字获取所需的行为。

static void Main(string[] args)
{
    dynamic d = new A();
    // Call first method
    MyMethod(d);

    d = new B();
    // Call the second method
    MyMethod(d);

    Console.ReadLine();
}

答案 2 :(得分:0)

它没有调用第二种方法,因为对b本身的引用属于A类型。虽然b包含对B实例的引用,但这不是B的实际类型,因此选择使用A引用的重载。