协变(out)和逆变(in)仅适用于接口和委托,协变允许更具体的类型赋给更宽泛的类型变量,仅限返回值、get访问器等输出位置;逆变则用于输入位置如方法参数,仅限接口和委托;类不支持协变或逆变。协变(out)只适用于接口和委托,且只能用在输出位置协变允许你把更具体的类型赋给更宽泛的类型变量,比如 IEnumerable<string> 能赋给 IEnumerable<object>。但这不是所有泛型都支持------只有标记了 out 的类型参数才允许协变,而且它**只能出现在返回值、属性 get 访问器、方法返回类型中**,不能出现在参数、字段或 set 访问器里。常见错误现象:void Add(T item) 里用了 out T,编译直接报错 CS1961:"类型参数 T 具有无效的方差"。IEnumerable<T>、IComparer<out T>、Func<out T> 是典型协变接口/委托自定义接口要协变,必须显式写 interface IProducer<out T>,且所有 T 出现位置都得是"只读"的类不支持协变或逆变------class List<out T> 是非法语法逆变(in)只用于输入位置,且仅限接口和委托逆变让你把更宽泛的类型传给更具体的期望,比如 Action<object> 可以赋给 Action<string>(因为 string 是 object 的子类,而 Action 只消费参数,不返回它)。逆变的关键是:类型参数只能出现在**参数位置**,不能用于返回值或属性 get。使用场景:当你需要一个"能处理任意父类的委托",但实际只想传子类实例时,逆变就省去了手动包装。Action<in T>、IComparer<in T>、Predicate<in T> 是典型逆变接口/委托错误写法:T GetFirst() 出现在 interface IConsumer<in T> 里 → 编译失败 CS1961注意 IComparer<T> 同时支持 in 和 out?不对。.NET 中它是 IComparer<in T>,因为比较逻辑只接收两个 T 参数,不返回 T泛型类永远不支持 in/out,别试了你没法给 class Box<T> 加 in 或 out。C# 语言规范明确禁止------类的类型参数必须是不变的(invariant)。这是因为类既有输入(构造函数、方法参数),又有输出(属性、返回值),无法统一满足协变或逆变约束。 Tellers AI Tellers是一款自动视频编辑工具,可以将文本、文章或故事转换为视频。
相关推荐
cui_ruicheng1 小时前
MySQL(四):数据类型与字段设计Full Stack Developme2 小时前
JVM 与 Linux 交互的核心原理皮皮学姐分享-ppx2 小时前
政府绿色采购数据库(2015-2024.3)珺毅同学2 小时前
YOLO生成预测json标签迁移问题骑士雄师2 小时前
18.4 长期记忆可修改版cfm_29142 小时前
JVM GC垃圾回收初步了解~小先生~3 小时前
Python从入门到放弃(一)天佑木枫3 小时前
第2天:变量与数据类型 —— 让程序记住信息闪电悠米4 小时前
黑马点评-Redis 消息队列-03_stream_consumer_groupDust-Chasing4 小时前
Claude Code源码剖析 - Claude Code 上下文压缩机制