定义

  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. OC 三方框架 - SDWebImage

    内部实现原理: 1. 下载图片 缓存, 并且需要下载进度 2. 下载图片 : 3.不需要缓存处理的下载 4. 使用GIF 图片使用:图片名字不要加上 .gif 因为内部已经做过处理了 GIF 内部实现 ...

  2. error: In function ‘void* opencv_showimg(void*)’:

    今天这个问题折磨了我一下午,终于知道是为什么了,心酸历程.....赶紧来记录一下 错误: /home/wj/workspace/Loitor_VI_Sensor_SDK_V1./SDK/src/cam ...

  3. vsftp 500 OOPS: cannot change directory:/home/xyp

    1.在linux终端下输入: > setsebool ftpd_disable_trans 1 (*如果出现Could not change active booleans: Invalid b ...

  4. JsonConvert.SerializeObject 空值处理

    var settings = new JsonSerializerSettings() { ContractResolver= new NullToEmptyStringResolver() }; v ...

  5. 【原创】有关Silverlight中 "Silverlight提示4004错误" 的解决方案及思路。

    今天下午再改一个页面xaml时没注意一个细节导致了这个错误,整整搞了1个小时.在这给大家参考参考. 出错原因: 总结:其实silverlight已经提示了 出错的细节信息了,没必要因为silverli ...

  6. windows,phalcon工具的安装使用

    一.使用工具之前,必须安装phalcon的扩展,也就是php_phalcon.dll动态链接库 phalcon官方地址:https://github.com/phalcon/cphalcon/rele ...

  7. NFS 挂载 + autofs

    NFS:Network File System RPC:Remote Procedure Call 一.手动挂载  (mount -t nfs 服务端IP:/共享目录  /本地挂载点) 客户端 1.安 ...

  8. fms +fme 视频直播

    1.安装fms 按默认安装即可 2.安装fme 安装完成后启动fme FMS URL是发布到fms的地址默认就可以, 然后点击 Connect 连接成功后左下角会出现connected的提示, 然后点 ...

  9. oracle建存储过程

    进入plsql命令行 [10:42:10 liuyi@localhost]/home/liuyi>sqlplus demo/demo@180.200.3.129/meboss 连接串格式:用户名 ...

  10. a标签点击后,保证后来的样式

    在个人中心中,左侧的菜单(a标签),点击之后,不能够应用新的样式 而在静态界面html 中表现正常,在修改成动态的就不行了 可能是a标签链接经过了后台,当前页面的this对象发生了变化,所以就不能够像 ...