《c#高级编程》第4章C#4.0中的更改(八)——协变和逆变

一、协变

C#协变是指在一些特定的情况下,可以将一个派生类型的实例赋值给其基类或接口类型的引用。这里的“派生类型”指的是从某个基类或接口继承并增加了新的成员的类型。

C# 4.0 引入了对协变和逆变的支持。其中,协变针对的是返回类型,逆变则针对参数类型。通过使用协变和逆变,可以使得某些代码更加简单、易读,并且减少需要编写的重复代码。

具体来说,协变的主要提升体现在以下方面:

  1. 委托类型的协变:在 C# 2.0 中,委托类型必须完全匹配,也就是说,委托类型的参数和返回类型必须与目标方法的参数和返回类型完全相同。但在 C# 3.0 中,引入了委托类型的协变功能,可以将一个返回类型为派生类型的方法赋值给一个返回类型为基类类型(或接口类型)的委托变量,这样可以避免显式地进行类型转换。例如:

    public delegate T MyDelegate<out T>();
    public class Animal { }
    public class Mammal : Animal { }
    public class Giraffe : Mammal { }
    
    // 协变: Giraffe 是 Mammal 的派生类, Mammal 是 Animal 的派生类
    MyDelegate<Giraffe> giraffe = () => new Giraffe();
    MyDelegate<Mammal> mammal = giraffe;
    MyDelegate<Animal> animal = giraffe;
    
  2. 泛型类型参数的协变:在 C# 4.0 中,可以使用 out 关键字来声明泛型接口或委托的类型参数是协变的。这样,就可以将一个泛型类型的实例赋值给其基类或接口类型的引用。例如:

    public interface IMyInterface<out T> { }
    public class Animal { }
    public class Mammal : Animal { }
    
    // 协变: Mammal 是 Animal 的派生类
    IMyInterface<Mammal> mammal = null;
    IMyInterface<Animal> animal = mammal;
    

总之,C#的协变功能使得代码更加简洁、清晰,并且提高了代码的可读性和可维护性。
二、逆变
C#逆变是指在一些特定的情况下,可以将一个基类或接口类型的引用赋值给其派生类型的实例。这里的“派生类型”指的是从某个基类或接口继承并增加了新的成员的类型。

C# 4.0 引入了对协变和逆变的支持。其中,协变针对的是返回类型,逆变则针对参数类型。通过使用协变和逆变,可以使得某些代码更加简单、易读,并且减少需要编写的重复代码。

具体来说,逆变的主要应用场景是:

  1. 委托类型的逆变:在 C# 2.0 中,委托类型必须完全匹配,也就是说,委托类型的参数和返回类型必须与目标方法的参数和返回类型完全相同。但在 C# 4.0 中,引入了委托类型的逆变功能,可以将一个接受基类类型(或接口类型)参数的方法赋值给一个接受派生类型参数的委托变量,这样可以避免显式地进行类型转换。例如:

    public delegate void MyDelegate<in T>(T arg);
    public class Animal { }
    public class Mammal : Animal { }
    public class Giraffe : Mammal { }
    
    // 逆变: Animal 是 Mammal 的基类, Mammal 是 Giraffe 的基类
    MyDelegate<Animal> animal = (a) => Console.WriteLine(a.GetType());
    MyDelegate<Mammal> mammal = animal;
    MyDelegate<Giraffe> giraffe = animal;
    
  2. 泛型接口类型参数的逆变:在 C# 4.0 中,可以使用 in 关键字来声明泛型接口的类型参数是逆变的。这样,就可以将一个基类或接口类型的引用赋值给其派生类型的实例。例如:

    public interface IMyInterface<in T> { }
    public class Animal { }
    public class Mammal : Animal { }
    
    // 逆变: Animal 是 Mammal 的基类
    IMyInterface<Animal> animal = null;
    IMyInterface<Mammal> mammal = animal;
    

总之,C#的逆变功能使得代码更加简洁、清晰,并且提高了代码的可读性和可维护性。

posted @ 2023-04-25 13:43  GroundSoft  阅读(32)  评论(0编辑  收藏  举报