调用重载的方法时,编译器会根据实参的数量和类型的不同选择调用适合的方法。那么如果一次调用使用的实参有多个重载方法可以适合时,编译器会怎么选择呢?见下面的程序。
class Base{}
class Derive : Base{}
class DDerive : Derive{}
public class TestMain
{
[STAThread]
static void Main(string[] args)
{
DDerive dd = new DDerive();
Base b = dd;
Derive d = dd;
TestMothed(b);
TestMothed(d);
TestMothed(dd);
}
static void TestMothed(Base b)
{
Console.WriteLine("Base");
}
static void TestMothed(Derive d)
{
Console.WriteLine("Derive");
}
}
class Derive : Base{}
class DDerive : Derive{}
public class TestMain
{
[STAThread]
static void Main(string[] args)
{
DDerive dd = new DDerive();
Base b = dd;
Derive d = dd;
TestMothed(b);
TestMothed(d);
TestMothed(dd);
}
static void TestMothed(Base b)
{
Console.WriteLine("Base");
}
static void TestMothed(Derive d)
{
Console.WriteLine("Derive");
}
}
上面程序可以看到,第2次和第3次的TestMothed方法调用显然两个TestMothed重载方法都适用。而第1次TestMothed的调用虽然实参b的类型是Base类,但b引用的对象则是DDerive类。这三次方法调用会调用哪个重载方法呢?运行结果如下:
Base
Derive
Derive
再把代码修改一下:
class Base{}
interface IInterface{}
class Derive : Base, IInterface{}
public class TestMain
{
[STAThread]
static void Main(string[] args)
{
Derive d = new Derive();
TestMothed(d);
}
static void TestMothed(Base b)
{
Console.WriteLine("Base");
}
static void TestMothed(IInterface i)
{
Console.WriteLine("IInterface");
}
}
这段代码根本不能编译,因为Base类和IInterface接口都是Derive类的基类(接口)且离Derive类一样近。
再把代码修改一下:
class Base{}
class Derive : Base{}
class DDerive : Derive{}
public class TestMain
{
[STAThread]
static void Main(string[] args)
{
DDerive dd = new DDerive();
TestMothed(dd, dd);
}
static void TestMothed(Base b, Derive d)
{
Console.WriteLine("Base, Derive");
}
static void TestMothed(Derive d, Base b)
{
Console.WriteLine("Derive, Base");
}
}
class Derive : Base{}
class DDerive : Derive{}
public class TestMain
{
[STAThread]
static void Main(string[] args)
{
DDerive dd = new DDerive();
TestMothed(dd, dd);
}
static void TestMothed(Base b, Derive d)
{
Console.WriteLine("Base, Derive");
}
static void TestMothed(Derive d, Base b)
{
Console.WriteLine("Derive, Base");
}
}
这段代码同样不能编译,因为两个TestMothed重载方法的形参离实参都是一近一远。
从结果我们可以发现,如果一次调用使用的参数有多个重载方法可以适合时,编译器将根据以下原则选择重载方法:
1、优先选择形参与实参类型严格匹配的重载方法,而实参所引用的对象类型不以考虑;
2、当有多个重载方法的形参都是实参的基类(接口)时,则选择形参是离实参最近的基类(接口)的重载方法。
3、当有多个重载方法的形参都是实参的基类(接口)时,不能同时存在两个形参是离实参最近的基类(接口)的重载方法,否则不能编译。
4、若存在两个拥有两个以上形参的重载方法,它们有两个形参分别离实参一近一远,则不能编译。