新建一个.NET Core控制台项目,我们来看看C#中重载方法的一些注意事项。
C#中多个重载方法之间的参数如果有继承关系,那么调用方法时,会调用与传入参数类型最接近的重载方法
我们来举个例子,下面我们定义了两个重载方法Do,它们的参数类型A和B是继承关系,类B继承类A,那么我们在调用Do方法时,到底调用的是哪一个重载呢?
代码如下:
using System;
namespace NetCoreOverloadParameters
{
///
/// 类A
///
class A
{
}
///
/// 类B继承类A
///
class B : A
{
}
class Program
{
///
/// 方法Do
///
/// 参数类型为A
static void Do(A a)
{
Console.WriteLine("Do A");
}
///
/// 方法Do
///
/// 参数类型为B
static void Do(B a)
{
Console.WriteLine("Do B");
}
static void Main(string[] args)
{
A a = new B();
B b = new B();
Do(a);//因为传入Do方法的类型是A,所以这里调用Do(A a)
Do(b);//因为传入Do方法的类型是B,所以这里调用Do(B a)
Do(new A());//因为传入Do方法的类型是A,所以这里调用Do(A a)
Do(new B());//因为传入Do方法的类型是B,所以这里调用Do(B a)
Do(null);//当传入null给Do方法时,这里调用的是Do(B a),说明优先调用的是继承链中参数为子类B的重载方法
Do((A)null);//因为传入Do方法的类型是A,所以这里调用Do(A a)
Console.WriteLine("Press any key to end...");
Console.ReadKey();
}
}
}
执行结果如下:
所以我们可以看到,实际上在每次调用Do方法时,C#会选择调用和传入参数类型最接近的重载方法。
如果我们现在注释掉代码中的重载方法Do(B a),由于现在代码中只有一个Do方法了,所以所有的调用都会调用Do(A a):
using System;
namespace NetCoreOverloadParameters
{
///
/// 类A
///
class A
{
}
///
/// 类B继承类A
///
class B : A
{
}
class Program
{
///
/// 方法Do
///
/// 参数类型为A
static void Do(A a)
{
Console.WriteLine("Do A");
}
///
/// 方法Do
///
/// 参数类型为B
//static void Do(B a)
//{
// Console.WriteLine("Do B");
//}
static void Main(string[] args)
{
A a = new B();
B b = new B();
Do(a);
Do(b);
Do(new A());
Do(new B());
Do(null);
Do((A)null);
Console.WriteLine("Press any key to end...");
Console.ReadKey();
}
}
}
执行结果如下:
C#中如果有签名相同的泛型方法和非泛型方法,那么C#会优先考虑调用非泛型方法
我们来看看下面这个例子,我们在代码中,定义了三个Do方法,其中一个非泛型方法和两个泛型方法,那么我们在调用Do方法时,C#会优先考虑调用非泛型方法:
using System;
namespace NetCoreOverloadParameters
{
///
/// 类A
///
class A
{
}
///
/// 泛型静态类Container
///
static class Container
{
///
/// 方法Do
///
/// 参数类型为A
public static void Do(A a)
{
Console.WriteLine("Do A");
}
///
/// 方法Do
///
/// 参数类型为T1
public static void Do(T1 t1)
{
Console.WriteLine("Do T1");
}
///
/// 方法Do
///
/// 类型参数T2
/// 参数类型为T2
public static void Do(T2 t2)
{
Console.WriteLine("Do T2");
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
Container.Do(a);//C#会优先考虑非泛型的方法,来匹配传入Do方法的类型,所以这里会调用重载方法Do(A a),这会导致泛型重载方法Do(T1 t1),无法被调用到
Container.Do((object)a);//将静态类Container的类型参数定义为object后,再给Do方法传入object类型的参数,这样C#就会优先调用泛型重载方法Do(T1 t1)了
Container.Do(a);//由于这里我们显式声明了类型参数,所以C#知道我们在这里要调用的是重载方法Do(T2 t2)
Console.WriteLine("Press any key to end...");
Console.ReadKey();
}
}
}
执行结果如下:
C#中扩展方法和非扩展方法的重载
https://www.cnblogs.com/OpenCoder/category/1132736.html