协变:派生类=>基类
假设有这样一个类:
class Person : ICloneable { public object Clone() { Console.WriteLine("this is Clone"); return new Person(); } }
但是由于我们知道是返回一个Person类的实例,所以返回类型 object 写在这里总会觉得很别扭,我们希望写成:
class Person : ICloneable { public Person Clone() { Console.WriteLine("this is Clone"); return new Person(); } }
显然,这是错的!虽然这是错的,但这就是返回类型的协变性,只是非泛型接口和方法重载不支持这一特性.
如果一定要这样写,只能使用显示接口实现:
class Person : ICloneable { object ICloneable.Clone() { Console.WriteLine("this is ICloneable.Clone"); return Clone(); } public Person Clone() { Console.WriteLine("this is Clone"); return new Person(); } }
如果定义的是 ICloneable类型, 则调用上面的方法;
如果定义的是 Person 类型,则调用下面的方法;
ICloneable ic = new Person(); ic.Clone(); Person p = new Person(); p.Clone();
逆变:基类=>派生类
假设我们有这样一个类:
class Person { public virtual void Process(Person person) { Console.WriteLine("this param is person"); } }
我们想在派生类中写如下一个方法:
class Student : Person { public override void Process(object o) { Console.WriteLine("this param is obj"); } }
看起来很合理, 因为 object 是基类,肯定可以接受 Person 类的实例呀,这称为参数类型的逆变性
但实际上,和协变一样,非泛型接口接口和方法不支持
委托返回类型的协变性:
一个返回值为 基类 的委托变量,可以接收一个返回值为 派生类 的委托实例
class Program { public delegate Parent DelgParent(); public delegate Child DelgChild(); static void Main(string[] args) { DelgParent del1 = Method1; DelgChild del2 = Method2; del1 = Method2; //del2 = Method1;//异常,返回类型错误 Console.ReadKey(); } public static Parent Method1() { return null; } public static Child Method2() { return null; } } class Parent { } class Child : Parent { }
委托参数的逆变性:
一个参数为 派生类 的委托变量, 可以接收一个参数为 基类 的委托实例
class Program { delegate void PersonDelegate(Student s); static void Main(string[] args) { PersonDelegate pd = Test; pd(new Student()); Console.ReadKey(); } static void Test(Person p) { Console.WriteLine("person"); } }