c#入门-协变,逆变

一个bug

这是两个泛型列表。你不用在意他是什么,你只要知道他和数组很像就行。

List<string> strList = new List<string>() { "123", "456", "789" };
List<object> objList = new List<object>(3);

现在把第二个列表的内容,用第一个列表的内容覆写。

for (int i = 0; i < strList.Count&&i<objList.Count; i++)
{
	objList[i]= strList[i];
}

把一个值赋值给不同类型的变量。但因为变量类型和值的类型有继承关系,所以可以成立。
那么既然string类型可以赋值给object类型,那你有没有想过不访问元素,直接从外面进行赋值。
像这样:

List<string> strList = new List<string>() { "123", "456", "789" };
List<object> objList = strList;

首先告诉你,这种做法在数组上是可以的,但是按照c#的类型安全理念,不应该成立。
因为会发生以下错误:

string[] strArr = new string[] { "123", "456", "789" };
object[] objArr = strArr;

objArr[0] = 12;

这在编译时是可以通过的,但实际运行起来,会出现类型转换失败的异常。

协变逆变

泛型具有严格的限制,像上面那种使用方式是不允许的。
而协变逆变就是用来解开这种限制。
而协变逆变也有限制,不能对类使用,只能对接口或委托使用。
(因为他们不会储存字段,只有方法)。

协变

协变:和谐的变化,儿子随着时间流逝会当父亲。泛型填的是子类,可以迎合父类。
使用out关键字修饰泛型占位符,表示输出。修饰的泛型占位符仅能作为返回类型。

interface IOut<out T> 
{
	T GetValue();
}
class COut : IOut<string>
{
	public string GetValue() => "hello";
}
IOut<string> out1 = new COut();
IOut<object> out2 = out1;

因为这个接口中只有输出的泛型。
在输出的时候把string作为object看待是没有问题的。

逆变

逆变:大逆不道的变化,要父亲当儿子。泛型填的是父类,却要迎合子类。
使用in关键字修饰泛型占位符,表示输入。修饰的泛型占位符仅能作为参数类型。

interface IIn<in T> {

	void SetValue(T value);
} 
class CIn : IIn<object>
{
	public void SetValue(object value) { }
}
IIn<object>in1=new CIn();
IIn<string> in2 = in1;

因为这个接口中只有参数的泛型,
在作为参数的时候,把string作为object看待是没有问题的。

而泛型类中的字段,是技能作为输入,又能作为输出的存在。
所以协变逆变对泛型类不可用。

协变逆变不能把泛型参数装箱拆箱

所有的值类型不能参与协变逆变。

class CT<T> : IOut<T>, IIn<T>
{
	T IOut<T>.GetValue() => throw new NotImplementedException();
	void IIn<T>.SetValue(T value) => throw new NotImplementedException();
}
CT<Stream> ct = new CT<Stream>();
IIn<FileStream> Iin = ct;
IOut<object> Iout = ct;

Iout = new CT<int>();
IIn<int> Iin2 = new CT<object>();

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值