c#协变与逆变心得
对于协变与逆变,始终记住三个原则,记住这三点就一切清晰了!
1.不管协变还是逆变,最终遵循的类型变换是===》子类转换为父类,比如string=》object;即被派生类转为派生类;
2.协变修饰为out,协变时,协变修饰的类型参数只能作为返回值!不能用于输入参数,编译不过去;
3.逆变修饰符为in,逆变时,逆变修饰的类型参数只能作为输入参数!不能用于返回值,编译不过去;
/// <summary> /// /// </summary> /// <typeparam>逆变类型参数</typeparam> /// <typeparam>协变类型参数</typeparam> interface IDemo<in TN, out TX> { /// <summary> ///协变,out修饰类型参数Y只能用于返回值! /// </summary> /// <returns></returns> TX Xb(); /// <summary> /// 逆变,in 修饰的类型参数T只能用于输入参数! /// </summary> /// <param></param> void Nb(TN param); /// <summary> /// 组合的例子 /// </summary> /// <param></param> /// <returns></returns> TX Get(TN param); } class A:IDemo<object,string> { public string Xb() { throw new NotImplementedException(); } public void Nb(object param) { throw new NotImplementedException(); } public string Get(object param) { throw new NotImplementedException(); } } class B:IDemo<string,object> { public object Xb() { throw new NotImplementedException(); } public void Nb(string param) { throw new NotImplementedException(); } public object Get(string param) { throw new NotImplementedException(); } }
static void Main() { //参数类型完全一样,,可以编译通过 IDemo<string,object> correctDemo=new B(); //注意correctDemo2的声明方式 IDemo<string, object> correctDemo2= new A(); //正确的方式 object result= correctDemo2.Get("111"); //参数类型错误 //correctDemo2.Get(new object()); //无法协变和逆变 //IDemo<object, string> wrongDemo = new B(); }
分析
1.我们通过IDemo<string, object>声明了correctDemo2,所以correctDemo2的Get方法的签名是object Get(string p);注:根据原则2、3,string为逆变参数,只能做输入参数,object为协变参数,只能做返回值
2.根据类A的定义,我们得出类A的Get方法的签名是string Get(object param)
3.correctDemo2的引用指向了类A的实例!所以correctDemo2执行时,实际是执行的方法其实是酱紫的string Get(object param),就是A的Get方法
4.但是我们在调用correctDemo2的Get方法时传递的参数是string类型的啊!可A的Get方法接受的是object类型的参数啊!OK我们的原则1出场(回上面瞅瞅),string=》object遵循被派生类转为派生类的原则;所以Get方法可以执行了
5.然后继续,A的Get方法执行后返回的结果是string类型!而correctDemo2实际是接受一个object类型的结果;OK我们的原则1再出场,string=》object遵循被派生转为派生类的原则;所以Get方法成功返回结果~
6.第四步就是逆变的过程,第五步就是协变的过程;
这是correctDemo2在调用时显示的信息,需要string类型的参数,返回object的结果;
然后我们调试的时候用即时窗口看看correctDemo2
原来是A类型,只不过调用时是通过接口的方法签名调用的
然后再看看correctDemo2的方法
实际上是object的参数,string的结果;
整个的执行过程是酱紫的;
图片较宽,可以右键,在新窗口中打开
温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/42914.html
- 上一篇:C#导出Excel总结
- 下一篇:c#Socket客户端和服务端的信息发送