C# 协变和逆变方法 C#泛型中的in和out关键字如何使用
发布时间 - 2026-01-24 00:00:00 点击率:次协变out用于只含输出位置(如返回值、只读属性)的泛型接口或委托,如IEnumerable、Func;逆变in用于只含输入位置(如方法参数)的泛型接口或委托,如IComparer、Action。
协变 out 用在什么接口/委托上?
协变允许你用更具体的类型替换泛型参数,但前提是该参数只作为返回值出现。所以 out 只能用于输出位置:接口或委托的泛型参数如果只出现在返回类型中(比如方法返回值、只读属性的 get 访问器),才能加 out。
常见可协变的接口有 IEnumerable、IReadOnlyList、Func(无参返回 T 的委托)。例如:
IEnumerablestrings = new List (); IEnumerable
但不能用于 List 这种可变集合——它有 Add(T item),T 出现在输入位置,不满足协变条件。
逆变 in 为什么只能用于输入参数?
逆变允许你用更通用的类型替换泛型参数,但它要求该参数只作为输入参数出现。所以 in 只能用于方法参数、委托参数等“进来的”位置。
典型例子是 IComparer 和 Action:
IComparer
因为 Compare(T x, T y) 中的 T 只用来接收参数,不返回 T,所以可以安全地“向上兼容”。
注意:一个泛型参数不能同时是 in 和 out;也不能在同一个接口里既当输入又当输出(否则编译器会报错)。
自定义接口加 in 或 out 的硬性限制
你不能随便给任意泛型接口加 in 或 out,编译器会严格检查所有成员中的使用位置:
- 加
out T→ 所有T必须出现在仅输出位置:返回类型、只读属性、委托返回值等 - 加
in T→ 所有T必须出现在仅输入位置:方法参数、委托参数、ref/out参数的类型不允许(它们是双向的,违反纯输入)
例如这个接口无法标记为 out:
interface Bad{ T Get(); // ✅ 输出 void Set(T value); // ❌ 编译错误:T 出现在输入位置 }
委托中 Func 和 Action 的 in/out 已经预设好了
不必自己写 delegate 声明,.NET 内置委托已经按规则标注:
-
Func:TResult 是out -
Func:T 是in,TResult 是out -
Action:T 是in -
Predicate:T 是in -
Comparison:T 是in
这意味着你可以直接利用这些协变/逆变能力做类型转换,但别试图把 Action 赋给 Action——那是反的,会编译失败

Action action = x => Console.WriteLine(x); Action stringAction = action; (因为 string 可安全传给期望 object 的地方)。
真正容易被忽略的是:协变和逆变只对引用类型生效。如果你用 int、struct,哪怕满足位置要求,也无法进行这种隐式转换——编译器不会报错,但转换语句根本不会通过类型检查。
# c#
# 编译错误
# .net
# 隐式转换
# 为什么
# red
# gate
# String
# Object
# int
# 接口
# 引用类型
# Struct
# 访问器
# Delegate
# 委托
# 泛型
# 类型转换
# console
# 出现在
# 逆变
# 返回值
# 的是
# 你用
# 子类
# 报错
# 也不
# 好了
# 你可以
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
桂林网站制作公司有哪些,桂林马拉松怎么报名?
专业商城网站制作公司有哪些,pi商城官网是哪个?
Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程
javascript如何操作浏览器历史记录_怎样实现无刷新导航
Laravel如何使用Telescope进行调试?(安装和使用教程)
油猴 教程,油猴搜脚本为什么会网页无法显示?
制作旅游网站html,怎样注册旅游网站?
公司门户网站制作流程,华为官网怎么做?
Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】
Laravel如何使用withoutEvents方法临时禁用模型事件
免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?
Win11关机界面怎么改_Win11自定义关机画面设置【工具】
如何用搬瓦工VPS快速搭建个人网站?
怎样使用JSON进行数据交换_它有什么限制
Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理
Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面
如何挑选最适合建站的高性能VPS主机?
如何在 Pandas 中基于一列条件计算另一列的分组均值
Linux系统命令中tree命令详解
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置
Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】
Laravel怎么返回JSON格式数据_Laravel API资源Response响应格式化【技巧】
PHP 500报错的快速解决方法
Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区
HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
如何基于PHP生成高效IDC网络公司建站源码?
Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】
Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比
Python图片处理进阶教程_Pillow滤镜与图像增强
Laravel如何使用Vite进行前端资源打包?(配置示例)
Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案
Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践
Laravel观察者模式如何使用_Laravel Model Observer配置
如何在腾讯云服务器快速搭建个人网站?
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
nodejs redis 发布订阅机制封装实现方法及实例代码
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
如何在企业微信快速生成手机电脑官网?
动图在线制作网站有哪些,滑动动图图集怎么做?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
如何正确选择百度移动适配建站域名?
Swift中循环语句中的转移语句 break 和 continue
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
如何在IIS7上新建站点并设置安全权限?
网站页面设计需要考虑到这些问题
安克发布新款氮化镓充电宝:体积缩小 30%,支持 200W 输出
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?

