c# 协变与抗变
定义
- 协变:与原始类型转换方向相同的可变性称为协变。
- 抗变:与派生类型转换方向相同的可变性称为抗变。
补充:
- 参数是协变的,可以使用派生类对象传入需要基类参数的方法,反之不行
- 返回值是抗变的,不能使用派生类对象接收返回了基类对象的方法返回值,反之可以
代码展示
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# 协变与抗变的更多相关文章
- C#中协变与抗变(逆变)
泛型在.NET 2.0中正式的引入.在使用泛型的过程中,联系上面向对象的继承性.往往很容易想当然敲出类似以下代码 List<Animal> animalLst=new List<Do ...
- 让我们用心感受泛型接口的协变和抗变out和in
关键字out和in相信大家都不陌生,系统定义的很多泛型类型大家F12都或多或少看见了.但是实际中又很少会用到,以前在红皮书里看到,两三页就介绍完了.有的概念感觉直接搬出来的,只是说这样写会怎样,并没有 ...
- C#泛型中的抗变和协变
在.net4之前,泛型接口是不变的..net4通过协变和抗变为泛型接口和泛型委托添加了一个重要的拓展 1.抗变:如果泛型类型用out关键字标注,泛型接口就是协变的.这也意味着返回类型只能是T. 实例: ...
- 《C#高级编程》学习笔记------抗变和协变
1.协变和抗变 在.NET 4之前,泛型接口是不变的..NET 4通过协变和抗变为泛型接口和泛型委托添加了一个重要的扩展.协变和抗变指对参数和返回值的类型进行转换.例如,可以给一个需要Shape参数的 ...
- 解读经典《C#高级编程》最全泛型协变逆变解读 页127-131.章4
前言 本篇继续讲解泛型.上一篇讲解了泛型类的定义细节.本篇继续讲解泛型接口. 泛型接口 使用泛型可定义接口,即在接口中定义的方法可以带泛型参数.然后由继承接口的类实现泛型方法.用法和继承泛型类基本没有 ...
- 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 ...
- .NET C#杂谈(1):变体 - 协变、逆变与不变
0. 文章目的: 介绍变体的概念,并介绍其对C#的意义 1. 阅读基础 了解C#进阶语言功能的使用(尤其是泛型.委托.接口) 2. 从示例入手,理解变体 变体这一概念用于描述存在继承关系的 ...
- C#
1.类型推导 ; Console.WriteLine(age.GetType().ToString()); var 关键字还可以配合生成匿名类型,如: , Time = }: 如果有可以将对象转成JS ...
- C#_基础:委托速讲
1定义:委托=函数指针 C# public delegate void Test(string str); 等价C++ public void (*Test)(string str): 委托赋值(初始 ...
随机推荐
- 对象之int介绍
#Auther Bob #--*--conding:utf-8 --*-- #创建两个int的对象,age1和age2 age1 = 10 age2 = int(1) #查看对象的类 print(ty ...
- OC -网络请求 - NSURLConnection - GET
#import "ViewController.h" @interface ViewController ()<NSURLConnectionDataDelegate> ...
- webkit开源项目
WebKitOpen Source Web Browser Engine Blog Downloads Feature Status Reporting Bugs Contribute Getting ...
- Zookeeper 系列(四)ZKClient API
Zookeeper 系列(四)ZKClient API 环境准备: <dependency> <groupId>com.101tec</groupId> <a ...
- Mockplus教程:分分钟搞定APP首页原型设计
Mockplus是一款快速原型设计工具,支持包括APP原型在内的多种原型与线框图设计.除了快速,Mockplus广受欢迎更因为它极低的上手门槛.今天小编就为大家展示如何用Mockplus在3分钟内完成 ...
- 为什么const对象只能调用const成员函数,而不能调用非const成员函数?
在c++中,我们可以用const来定义一个const对象,const对象是不可以调用类中的非const成员函数,这是为什么呢?下面是我总结的一些原理. 假设有一个类,名字为test代码如下: clas ...
- Unsorted, maximum ==> sorted
https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...
- phoenix错误
spark集群与phoenix进行数据请求时报错: 2018-06-15 17:13:30,158 INFO - Starting task 15.3 in stage 116.0 (TID 6832 ...
- 2018.09.16 bzoj3626: [LNOI2014]LCA(树链剖分)
传送门 树链剖分好题. 对于每个点维护一个值vi" role="presentation" style="position: relative;"&g ...
- 2018.08.18 NOIP模拟 game(数位dp)
Game 题目背景 SOURCE:NOIP2015-SHY4 题目描述 Alice 和 Bob 正在玩一个游戏,两个人从 1 轮流开始报数,如果遇到 7 的倍数或者遇到的这个数的十进制表示中含 7 , ...