18协变和逆变
概念
协变:以out修饰的泛型类型叫做协变类型,协变只能返回(当返回值),用于返回参数,协变T只能用来当返回值使用
逆变:以in修饰的泛型类型叫做逆变类型,逆变只能当参数传进来,用于接收参数,逆变T只能用来当参数传递
协变和逆变都是单向的。in可读不可写,out可写不可读
创建两个类,基类:Person,子类:Student
public class Person
{
public int Id { get; set; }
public string UserName { get; set; }
}
public class Student : Person
{
}
协变
我们发现,如下代码会报错,虽然里氏转换子类可以给父类,但是这里不行,因为List
List<Person> persons = new List<Student>();
但是,这样就可以,因为List实现了IEnumerable接口,也就是继承了IEnumerable,根据里氏转换,可以将子类赋值给父类,而且IEnumerable
IEnumerable<Person> persons = new List<Student>();
原理是因为IEnumerable本身就是协变,它里面的泛型用out进行修饰了。
协变:父类接收子类
我们模仿IEnumerable接口做个测试。,创建一个协变接口和实现这个接口
//协变接口
public interface IMyOut<out T>
{
T GetT();
}
//实现协变接口
public class MyOut<T> : IMyOut<T>
{
public T GetT()
{
return default(T);
}
}
再Main里调用发现没问题
IMyOut<Person> persons = new MyOut<Student>();
persons.GetT();
逆变:子类接收父类
//逆变接口
public interface IMyIn<in T>
{
void GetT(T t);
}
//实现逆变接口
public class MyIn<T> : IMyIn<T>
{
public void GetT(T t)
{
}
}
IMyIn<Student> students = new MyIn<Person>();
students.GetT(
new Student()
{
Id = 1,
UserName = "张三"
});
分类:
C#高级语法和底层原理
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构