0

0

C# 委托协变和逆变 C# delegate的in和out泛型修饰符如何使用

幻夢星雲

幻夢星雲

发布时间:2026-02-16 06:51:13

|

714人浏览过

|

来源于php中文网

原创

委托协变用out修饰返回类型,使func可赋值给func;逆变用in修饰参数类型,使action可接收action;二者均需泛型参数仅出现在对应位置且满足类型安全约束。

c# 委托协变和逆变 c# delegate的in和out泛型修饰符如何使用

委托协变:用 out 修饰返回类型,允许子类转父类

协变发生在委托的返回值上。当你声明一个返回 string 的委托,却想用它指向返回 object 的方法时,编译器会报错——除非你在泛型参数上加 out。因为 stringobject 的子类,而“更具体的类型能安全当更宽泛的类型用”就是协变的本质。

典型场景是统一处理不同具体类型的工厂或转换逻辑:

  • Func<t></t> 内置委托本身就用了 out T,所以 Func<string></string> 可赋值给 Func<object></object>
  • 自定义委托必须显式加 out,且该参数只能出现在返回位置(不能作参数、不能在泛型约束中被用作基类)
  • 错误写法:public delegate T MyFunc<t>() where T : class</t> —— 没有 out 就不支持协变,MyFunc<string></string> 无法转成 MyFunc<object></object>

委托逆变:用 in 修饰参数类型,允许父类转子类

逆变作用于委托的输入参数。比如你有一个接受 object 的委托,但实际想传入只处理 string 的方法——这看似危险,实则安全:只要方法能处理更宽泛的输入,那传更具体的子类当然没问题。这时就得靠 in

常见于事件处理器、比较器、谓词等以输入为主的操作:

Clips AI
Clips AI

自动将长视频或音频内容转换为社交媒体短片

下载
  • Action<t></t>Predicate<t></t> 都用了 in T,所以 Action<object></object> 可接收 Action<string></string>
  • in 参数只能出现在形参位置,不能用于返回值、不能参与 where T : SomeBase 这类约束(否则协变/逆变会被禁用)
  • 若委托同时有输入和输出,可混合使用:Func<in t out r></in>,.NET 中的 Func<t tresult></t> 就是这样设计的

为什么加了 in/out 还编译失败?常见限制条件

协变和逆变不是万能的,C# 对其施加了严格的类型安全性检查。即使语法正确,以下情况仍会拒绝转换:

  • 泛型参数出现在「非协变/逆变位置」:比如 out T 却在方法体内把 T 当字段类型存储,或作为 ref/out 参数传递
  • 存在装箱/拆箱隐式转换干扰:比如 Func<int></int> 不能转成 Func<object></object>,因为 int 是值类型,object 是引用类型,这不是继承关系而是装箱,out 不覆盖此规则
  • 委托签名不匹配:协变只影响返回类型,参数数量、顺序、名称、是否 params 等仍需完全一致
  • 跨程序集时,目标框架版本太低(如 .NET Framework 4.0 之前不支持泛型变体)

实际调试时怎么快速判断该用 in 还是 out

别记规则,看数据流向。打开你的委托定义,盯住那个泛型参数 T

  • 如果 T 只出现在返回值位置(或 yield returnget 访问器),就用 out T
  • 如果 T 只出现在参数位置(包括 ref 以外的普通参数、params T[]),就用 in T
  • 如果 T 同时出现在参数和返回值里(比如 T DoSomething(T input)),那它既不能协变也不能逆变,不能加任何修饰符
  • VS 提示 “cannot convert … because the type parameter … is not valid variance position” 就说明你放错地方了

真正容易被忽略的是:变体只对泛型委托类型生效,对具体委托实例(如 new Func<string>(...)</string>)没意义;而且一旦用了 in/out,该参数在委托体内就变成只读(协变返回值不可作为输入,逆变参数不可作为返回),这是编译器强制的保护机制。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

730

2023.08.02

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

730

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

566

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

234

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

209

2025.08.29

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

603

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

21

2025.12.06

CSS position定位有几种方式
CSS position定位有几种方式

有4种,分别是静态定位、相对定位、绝对定位和固定定位。更多关于CSS position定位有几种方式的内容,可以访问下面的文章。

83

2023.11.23

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

145

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.5万人学习

C 教程
C 教程

共75课时 | 4.7万人学习

C++教程
C++教程

共115课时 | 17.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号