• 怎么理解逆变和协变?


    逆变和协变

    • 所谓逆变和协变,是.net 为了把面向对象的多态特性中的里氏转换 搬到泛型中依旧可以使用.

    协变:

    1. 现有以下类:

       public class Person
      {
          public long Id { get; set; }
          public string Name { get; set; }
      }
      public class Chinese:Person
      {
      ​
      }
      ​
      ​
      ​
      public interface XieBian<T>
      {
          T Print();
      }
      public class XieBianInstance<T> : XieBian<T>
      {
          public T Print()
          {
              throw new NotImplementedException();
          }
      }
    2. 根据面向对象多态特性,父类类型的变量可以指向子类类型的对象,那么下面这段代码按照理论来讲应该没有问题,可是编译器报错了:"无法将类型Chinese转换成Person"。原来泛型不支持。

      XieBian<Person> xie = new XieBianInstance<Chinese>();

      如果想这么使用,那就得使用协变,其实就是在接口或者委托的泛型上加上out关键字

      public interface XieBian<out T>
      {
          T Print();
      }
      public class XieBianInstance<T> : XieBian<T>
      {
          public T Print()
          {
              throw new NotImplementedException();
          }
      }

      注意:协变的泛型类型只能作用在接口或者委托上,并且协变的泛型类型只能用于接口方法或者委托的返回值

    逆变:

    1. 现有一个委托:

      public delegate void TestDel<T>(T obj);
    2. 乍一看貌似有点不和常理,子类类型变量指向父类类型对象。如果换一种思考方式,这个委托是要传一个Chinese类型的对象进去,因为Chinese是继承Person的,根据里氏转换可得,这么写也没问题。可问题还是报错了:"无法将类型Person转换成Chinese"。泛型是不支持这么做得。

      TestDel<Chinese> testDel = new TestDel<Person>((ch)=> { }); 

      如果想这么做,就必须利用逆变,其实就是在上面得委托泛型中加上int关键字

      public delegate void TestDel<in T>(T obj);

      改成这样,上面的代码就可以正常执行了。

      注意:逆变得泛型类型只能作用在接口和委托上,并且逆变得泛型类型只能用于接口方法或者委托的参数。不可用于返回值等等。

     

     逆变的接口示例:

      

    public interface NiBian<in T>
        {
            void Print(T obj);
        }
        public class NiBianInstance<T> : NiBian<T>
        {
    
            public void Print(T obj)
            {
                Console.WriteLine(obj.GetType().Name);
            }
        }
     static void Main(string[] args)
            {
                NiBian<Chinese> niBian = new NiBianInstance<Person>();
    
                Console.ReadKey();
            }

    ========================================结束线=========================================================

     

     

     

  • 相关阅读:
    【GDOI 2016 Day1】第二题 最长公共子串
    2016.5.21【初中部 NOIP提高组】模拟赛A​ 总结
    【GDOI2014模拟】雨天的尾巴
    树链剖分
    GDOI2016总结
    【GDOI 2016 Day2】第一题 SigemaGO
    【ZJOI2008】树的统计
    【GDOI2016模拟4.22】总结
    【NOIP2016提高A组模拟7.17】寻找
    【NOIP2016提高A组模拟7.17】锦标赛
  • 原文地址:https://www.cnblogs.com/norain/p/InversionAndCovariance.html
Copyright © 2020-2023  润新知