设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间23 现在时间23 缓存数据 荣耀也罢,屈辱也罢,都要以平和的心态去面对,少一些无奈与感慨,多一份从容和淡然。晚安!

荣耀也罢,屈辱也罢,都要以平和的心态去面对,少一些无奈与感慨,多一份从容和淡然。晚安!

查看: 821|回复: 3

C#实现协变和逆变案例

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:237
  • 打卡月天数:0
  • 打卡总奖励:3488
  • 最近打卡:2025-11-19 21:44:15
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
379
主题
350
精华
0
金钱
4646
积分
803
注册时间
2023-1-4
最后登录
2025-11-19

发表于 2023-2-12 10:11:52 | 显示全部楼层 |阅读模式
关于协变逆变,SolidMango的解释是比较可取的。有了协变,比如,在需要返回IEnumerable<object>类型的时候,可以使用IEnmerable<string>来替代;有了逆变,比如,在需要接收IComparable<string>类型形参方法中,可以使用IComparable<object>类型实参来替代。
协变

先来体会协变。有2个具有继承关系的父类和子类。
  1.     public class Animal
  2.     {
  3.         public string Name { get; set; }
  4.     }
  5.     public class Dog : Animal
  6.     {
  7.         public Dog(string dogName)
  8.         {
  9.             Name = dogName;
  10.         }
  11.     }
复制代码
现在有一个帮助类的方法的形参类型是父类集合IEnumerable<Animal>。
  1.     public class MyHelper
  2.     {
  3.         public void PrintAnimalNames(IEnumerable<Animal> animals)
  4.         {
  5.             foreach (var animal in animals)
  6.             {
  7.                 Console.WriteLine(animal.Name);
  8.             }
  9.         }
  10.     }
复制代码
有了协变,可以在PrintAnimalNames方法中传入IEnumerable<Dog>类型的实参替代IEnumerable<Animal>类型。
  1.         static void Main(string[] args)
  2.         {
  3.             List<Dog> dogs = new List<Dog>()
  4.             {
  5.                 new Dog("小狗petty"),
  6.                 new Dog("小狗lily")
  7.             };
  8.             //协变
  9.             IEnumerable<Animal> animals = dogs;
  10.             MyHelper myHelper = new MyHelper();
  11.             myHelper.PrintAnimalNames(animals);
  12.             Console.ReadKey();
  13.         }
复制代码
可见,在方法中基于基类接口类型的形参,调用该方法的时候可以传入派生类接口类型的实参。      
逆变

再来体会逆变。依然是2个具有继承关系的父类和子类。
  1.     public class Animal
  2.     {
  3.         public string Name { get; set; }
  4.         public int Age { get; set; }
  5.     }
  6.     public class Cat : Animal
  7.     {
  8.         public Cat(string catName, int catAge)
  9.         {
  10.             Name = catName;
  11.             Age = catAge;
  12.         }
  13.     }
复制代码
现在,我们想比较基类Animal的两个实例,为此,有必要专门写一个类让他实现IComparer<Animal>接口。
  1.     public class AnimalSizeComparator : IComparer<Animal>
  2.     {
  3.         public int Compare(Animal x, Animal y)
  4.         {
  5.             if (x != null && y != null)
  6.             {
  7.                 if (x.Age > y.Age)
  8.                 {
  9.                     return 1;
  10.                 }
  11.                 else if (x.Age == y.Age)
  12.                 {
  13.                     return 0;
  14.                 }
  15.                 else
  16.                 {
  17.                     return -1;
  18.                 }
  19.             }
  20.             else
  21.             {
  22.                 return -1;
  23.             }
  24.         }
  25.     }
复制代码
在帮助类中的方法中,针对Cat进行比较,方法接收IComparer<Cat>类型的形参。
  1.     public class MyHelper
  2.     {
  3.         public void CompareCats(IComparer<Cat> catComparer)
  4.         {
  5.             var cat1 = new Cat("小猫1",1);
  6.             var cat2 = new Cat("小猫2",2);
  7.             if (catComparer.Compare(cat2, cat1) > 0)
  8.             {
  9.                 Console.WriteLine("小猫2胜出");
  10.             }
  11.             else
  12.             {
  13.                 Console.WriteLine("小猫1胜出");
  14.             }
  15.         }
  16.     }
复制代码
有了逆变,客户端调用MyHelper的CompareCats方法时,可以传入IComparer<Animal>类型的实参。
  1.             IComparer<Animal> animalComparer = new AnimalSizeComparator();
  2.             MyHelper myHelper = new MyHelper();
  3.             myHelper.CompareCats(animalComparer);
  4.             Console.ReadKey();
复制代码
可见,在方法中基于派生类接口类型的形参,调用该方法的时候可以传入基类接口类型的实参。
总结:在本篇的场景中,派生类接口替代父类接口,称之为协变;父类接口代替派生类接口,称之为逆变。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对晓枫资讯的支持。如果你想了解更多相关内容请查看下面相关链接

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:24
  • 打卡月天数:0
  • 打卡总奖励:323
  • 最近打卡:2025-11-28 11:06:57
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
364
积分
50
注册时间
2023-1-9
最后登录
2025-11-28

发表于 2025-2-17 06:35:50 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
22
积分
24
注册时间
2022-12-27
最后登录
2022-12-27

发表于 2025-3-7 07:49:02 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
13
积分
6
注册时间
2023-11-3
最后登录
2023-11-3

发表于 3 天前 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼
4楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表