c#中关于协变性和逆变性(又叫抗变)详解

  今天回忆了之前看的《深入理解C#》这本书中的泛型章节,其中对泛型的可变性的理解。泛型可变性分两种:协变和逆变。逆变也又称为抗变。

 怎么理解这两个名词的意思:

  ①:协变即为在泛型接口类型中使用out标识的类型参数。协变的字面意思是“与变化的方向相同”②逆变那就是用in来标识的泛型接口类型的类型参数。逆变的字面意思是“与变化的方向相反”

  需要注意的是无论是协变还是逆变也只能在泛型接口中来使用。

  先来举个基本的例子,来加强你对可变性的理解。在C#中有隐式类型转换,比如:

  string str = "nibian";
  object str1 = str;
  Console.WriteLine(str1);

  

  大家都知道string类型是object类型的子类型,即string->object为子->父;从子类型到父类型的转换是隐式类型转换。

举个例子:

 interface IDemo<out T>
    {
        T Method(string str);
    }
    class One : IDemo<string>
    {
        public string Method(string str)
        {
            return str;
        }
    }
    class Two : IDemo<object>
    {
        public object Method(string str)
        {
            return str;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            IDemo<string> one = new One();
            IDemo<object> two;
            two = one;
            Console.WriteLine(two.Method("2222"));
        }
    }

  

通过观察代码我们发现IDemo<string>类型是IDemo<object>类型的子类型,可以将子类型隐式换转为父类型的用法就是协变。(这里必须要用out)

相反的我们在来看一下有关逆变的代码:

 interface IDemo<in T>
    {
        string Method(T str);
    }
    class One : IDemo<string>
    {
        public string Method(string str)
        {
            return str;
        }
    }
    class Two : IDemo<object>
    {
        public string Method(object str)
        {
            return str.ToString();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            IDemo<object> two = new Two();
            IDemo<string> one;
            one = two;
            Console.WriteLine(one.Method("2222"));
        }
    }

  同样的IDemo<string>类型是IDemo<object>类型的子类型,但是在这里我们却将父类型隐式转换为子类型的用法叫逆变。(这里必须要用in)

总结:协变和逆变就是在泛型接口类型将类型参数作为输入和输出的情况下,对类型间进行隐式转换的规律。

原文地址:https://www.cnblogs.com/yubabuneng/p/9506037.html

时间: 2024-10-13 15:05:57

c#中关于协变性和逆变性(又叫抗变)详解的相关文章

Java 协变性、逆变性 [转]

n  协变性.逆变性和无关性 在面向对象的计算机程序语言中,经常涉及到类型之间的转换,例如从具体类小猫到动物之间的类型转换(上行转换),或者从形状向三角形之间的转换(下行转换). 协变性(covariance).逆变性(contravariance)和无关性(invariant).他们都是用来描述类型转换的性质的术语,形式化的描述如下: 如果A和B是类型,f表示类型转换,≤表示子类型关系,(例如A≤B,表示A是B的子类)那么: 如果A≤B 则f(A) ≤ f(B) 那么f是协变的 如果A≤B 则

协变性和逆变性

1.协变性是指方法能返回从委托的返回类型派生的一个类型. 2.逆变性是指方法获取的参数可以是委托的参数类型的基类. =================================分割线================================= delegate Object MyCallback(FileStream s); string SomeMethod(Stream s); 如上面的例子,SomeMethod 的返回类型(string)派生自委托的返回类型(Object):这

ios中创建可以拖动的view原理和实现详解

有时候我们会需要在界面上拖动view;uiview是继承于uiresponder的,所以可以响应触摸相关的事件. 重点是以下一组方法: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet *)touches withEvent:(UIE

ios中创建可以拖动的view原理和实现详解(含代码)

有时候我们会需要在界面上拖动view;uiview是继承于uiresponder的,所以可以响应触摸相关的事件. 重点是以下一组方法: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet *)touches withEvent:(UIE

IOS中复制对象的用法及深拷贝和浅拷贝详解

亲爱的网友,我这里有套课程想和大家分享,如果对这个课程有兴趣的,可以加我的QQ2059055336和我联系. 课程内容简介 我们软件是基于移动设备的.所以我们必然的选择了安卓作为我们的开发工具.课程中,我们将简要的介绍Android的基本概念,然后进行我们的实战开发.在开发中,大家讲学习到基本的组件,适配UI,数据的存储,多线程下载,开机广播,闹钟提醒,短信发送等实际项目开发中碰到的有用的知识点.通过课程学习,让大家能够掌握Android软件开发的流程,注意点,及优化.帮助大家迅速的掌握Andr

[转]js中几种实用的跨域方法原理详解

转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作是不同的域. 下表给出了相对http://store.company.com/dir/page.html同源检测的结果: 要解决跨域的问题,我们可以使用以下几种方法: 一.通过jsonp跨域 在js中,我们直接用XMLHttpRequ

js中几种实用的跨域方法原理详解(转)

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作是不同的域. 下表给出了相对http://store.company.com/dir/page.html同源检测的结果: 要解决跨域的问题,我们可以使用以下几种方法: 一.通过jsonp跨域 在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的.但是,在页面上引入不同

Mybatis中接口和对应的mapper文件位置配置详解

Mybatis中接口和对应的mapper文件位置配置详解 原链接为:https://blog.csdn.net/fanfanzk1314/article/details/71480954 今天遇到一个问题是mybatis中接口和对应的mapper文件位置不同,而引起的操作也会不同,在网上找了好久最终找到了方法,这里就简单的解析一下: 我们知道在典型的maven工程中,目录结构有:src/main/java和src/main/resources,前者是用来存放java源代码的,后者则是存放一些资源

C#委托的协变性和逆变性

逆变性 只要函数参数与委托兼容,就能创建委托实例. 1 Button button = new Button(); 2 //public delegate void EventHandler(object sender, EventArgs e); 3 button.Click += LogPlainEvent; 4 //public delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e); 5 button.