定义

  1. 协变:与原始类型转换方向相同的可变性称为协变。
  2. 抗变:与派生类型转换方向相同的可变性称为抗变。

补充:

  1. 参数是协变的,可以使用派生类对象传入需要基类参数的方法,反之不行
  2. 返回值是抗变的,不能使用派生类对象接收返回了基类对象的方法返回值,反之可以

代码展示

public class 协变和抗变
{
/// <summary>
/// 基类
/// </summary>
public class Shape
{
public double Width { get; set; }
public double Height { get; set; }
public override string ToString() => $"width:{Width},height:{Height}";
}
/// <summary>
/// 派生类
/// </summary>
public class Rect : Shape
{ } #region 协变接口 /// <summary>
/// 协变接口 --------------- 协变--》属性和索引器必须实现get
/// </summary>
public interface IIndex<out T> // out声明接口为协变类型接口,继承了该接口的对象可以实现协变的隐式转换。 --对应调用方法中的shapes
{
T this[int index] { get; }
int Count { get; }
} /// <summary>
/// 接口实现类
/// </summary>
public class RectCollection : IIndex<Rect>
{
private Rect[] data = new Rect[3] {
new Rect{ Height=2,Width=5},
new Rect{ Height=3,Width=7},
new Rect{ Height=4.5,Width=2.9},
}; private static RectCollection _coll;
public static RectCollection GetRect() => _coll ?? (_coll = new RectCollection());
public Rect this[int index]
{
get
{
if (index < 0 || index > data.Length)
throw new ArgumentOutOfRangeException("index is out of range");
return data[index];
}
}
public int Count => data.Length;
} #endregion #region 抗变接口 /// <summary>
/// 抗变接口 --------------- 抗变--》属性和索引器必须实现set
/// </summary>
public interface IDisplay<in T> // in声明接口为抗变类型接口,继承了该接口的对象可以实现抗变的隐式转换。 --对应调用方法中的rectDisplay
{
void Show (T item);
} /// <summary>
/// 抗变实现类
/// </summary>
public class ShapeDisplay : IDisplay<Shape>
{
public void Show(Shape item) =>
Console.WriteLine($"{item.GetType().Name} width:{item.Width} height:{item.Height}");
} #endregion static void Main()
{
// 协变调用 Rect-》Shape 向派生程度低的类装换
IIndex<Rect> rects = RectCollection.GetRect();
IIndex<Shape> shapes = rects; // 如果IIndex接口的参数没有使用out修饰为协变,则转换报错(隐式转换会编译错误,显示转换会运行错误)
for (int i = 0; i < shapes.Count; i++)
{
Console.WriteLine(shapes[i]);
} // 抗变调用 Shape-》Rect 向派生程度高的类转换
IDisplay<Shape> shapeDisplay = new ShapeDisplay();
IDisplay<Rect> rectDisplay = shapeDisplay; // 如果IDisplay接口的参数没有使用in修饰为抗变,则转换报错
rectDisplay.Show(rects[0]);
}
}

c# 协变与抗变的更多相关文章

  1. C#中协变与抗变(逆变)

    泛型在.NET 2.0中正式的引入.在使用泛型的过程中,联系上面向对象的继承性.往往很容易想当然敲出类似以下代码 List<Animal> animalLst=new List<Do ...

  2. 让我们用心感受泛型接口的协变和抗变out和in

    关键字out和in相信大家都不陌生,系统定义的很多泛型类型大家F12都或多或少看见了.但是实际中又很少会用到,以前在红皮书里看到,两三页就介绍完了.有的概念感觉直接搬出来的,只是说这样写会怎样,并没有 ...

  3. C#泛型中的抗变和协变

    在.net4之前,泛型接口是不变的..net4通过协变和抗变为泛型接口和泛型委托添加了一个重要的拓展 1.抗变:如果泛型类型用out关键字标注,泛型接口就是协变的.这也意味着返回类型只能是T. 实例: ...

  4. 《C#高级编程》学习笔记------抗变和协变

    1.协变和抗变 在.NET 4之前,泛型接口是不变的..NET 4通过协变和抗变为泛型接口和泛型委托添加了一个重要的扩展.协变和抗变指对参数和返回值的类型进行转换.例如,可以给一个需要Shape参数的 ...

  5. 解读经典《C#高级编程》最全泛型协变逆变解读 页127-131.章4

    前言 本篇继续讲解泛型.上一篇讲解了泛型类的定义细节.本篇继续讲解泛型接口. 泛型接口 使用泛型可定义接口,即在接口中定义的方法可以带泛型参数.然后由继承接口的类实现泛型方法.用法和继承泛型类基本没有 ...

  6. C#中泛型方法与泛型接口 C#泛型接口 List<IAll> arssr = new List<IAll>(); interface IPerson<T> c# List<接口>小技巧 泛型接口协变逆变的几个问题

    http://blog.csdn.net/aladdinty/article/details/3486532 using System; using System.Collections.Generi ...

  7. .NET C#杂谈(1):变体 - 协变、逆变与不变

    0. 文章目的:   介绍变体的概念,并介绍其对C#的意义 1. 阅读基础   了解C#进阶语言功能的使用(尤其是泛型.委托.接口) 2. 从示例入手,理解变体   变体这一概念用于描述存在继承关系的 ...

  8. C#

    1.类型推导 ; Console.WriteLine(age.GetType().ToString()); var 关键字还可以配合生成匿名类型,如: , Time = }: 如果有可以将对象转成JS ...

  9. C#_基础:委托速讲

    1定义:委托=函数指针 C# public delegate void Test(string str); 等价C++ public void (*Test)(string str): 委托赋值(初始 ...

随机推荐

  1. nginx反向代理部署与演示(二)

    我们把LB01作为负载均衡器,WEB01和WEB02作为两台web服务器.   WEB01与WEB02虚拟主机配置如下:   我们修改nginx下的conf/nginx.conf文件,在http{}中 ...

  2. 在Struts2框架中使用OGNL表达式(在jsp页面中使用OGNL表达式)

    1. Struts2引入了OGNL表达式,主要是在JSP页面中获取值栈中的值 2. 具体在Struts2中怎么使用呢?如下步骤 * 需要先引入Struts2的标签库(在JSP页面的最上面位置) > ...

  3. Spring框架的事务管理之基于AspectJ的注解方式(重点掌握,最简单的方式)

    1. 步骤一:恢复转账的开发环境(具体开发环境实现见:https://www.cnblogs.com/wyhluckdog/p/10137283.html)2. 步骤二:applicationCont ...

  4. 屏幕录像专家exe视频批量翻录成视频avi格式

    笔者下载过一些视频,全部是屏幕录像专家录制的exe视频,这些视频没有密码,可以顺利打开看看. 有一日想把这些视频转换成wmv格式放到手机上查看.一个目录下有那么大exe视频.一个个转特别麻烦. 后来想 ...

  5. DOMNodeInserted监听div内容改变

    $('.cw-icon .ci-count').on('DOMNodeInserted',function(){ $(".settleup-content .cont_loading&quo ...

  6. 02 请求库之 selenium模块

      selenium模块   一 介绍 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动 ...

  7. Telnet 安装

    Telnet 安装 一.Telnet 安装 (1) 登录目标主机检测 telnet 服务是否正常 [root@localhost ~]# telnet localhost -bash: telnet: ...

  8. 原型工具之团队协作: Axure VS Mockplus

    一款软件产品的诞生,必然会经历一个过程:需求分析.设计.开发.测试.上线.如此反复迭代.而设计阶段中,原型设计.制作.交流.审核.迭代,是软件设计和开发的重要保障. 简单的一段话,我们可以解读出很多隐 ...

  9. KbmMW 4.30.00 发布

    今天早上,KbmMW发布了4.30.00 版,这个版本开始支持XE4 的WIN/WIN64/OSX. 暂时不支持ios开发,同时加强了通过JSON 的对象序列化.还有就是解决了我提交的几个有关 汉字处 ...

  10. 2018.10.12 NOIP模拟 字符处理(模拟)

    传送门 sb模拟,考试跟着sb了90分. 代码