我偶然发现了一个非常有趣的问题。提供以下代码:
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),这是一个设计上的决定,我想理解为什么会这样做,而且没有一个答案能回答这个问题。
/提笔
答案 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
引用的重载。