协变逆变从入门到精通:C#泛型中in/out不可不知的7个关键点

第一章:协变与逆变的核心概念解析

在类型系统中,协变(Covariance)与逆变(Contravariance)是描述类型转换如何影响复杂类型(如泛型、函数参数)行为的关键机制。它们决定了当类型之间存在继承关系时,由这些类型构造出的更复杂类型是否也能保持兼容性。

协变的基本表现

协变允许子类型替代父类型出现在某些位置。例如,在只读集合中,若 `Dog` 是 `Animal` 的子类,则 `List` 可被视为 `List` 的子类型。这种转换在支持协变的语言结构中是安全的。
  • 适用于返回值类型和只读数据结构
  • 增强接口灵活性,提升多态能力
  • 常见于函数返回类型和泛型接口中的输出位置

逆变的作用场景

逆变则相反,它允许父类型替代子类型,通常出现在输入参数的位置。例如,一个接受 `Animal` 参数的函数可以赋值给期望 `Dog` 参数的函数变量,因为传入 `Dog` 时仍满足 `Animal` 的契约。
// Go 不直接支持泛型协变/逆变,但可通过接口体现思想
type Processor interface {
    Process(animal *Animal) // 参数位置体现逆变潜力
}

type DogProcessor struct{}

func (dp *DogProcessor) Process(animal *Animal) {
    dog, _ := animal.(*Dog)
    // 处理 Dog 类型
}
该代码展示了函数参数接受基类,从而能处理其所有派生类,体现了逆变的思想。

协变与逆变对比表

特性协变逆变
方向保持类型顺序反转类型顺序
典型位置返回值、只读集合参数输入、可写入位置
安全性读操作安全写操作安全
graph LR A[Animal] --> B[Dog] C[List<Animal>] --> D[List<Dog>]:::covariant style D fill:#e0f7fa,stroke:#333 classDef covariant fill:#e0f7fa,stroke:#00695c;

第二章:C#中协变(out)的深入理解与应用

2.1 协变的基本语法与类型安全机制

协变(Covariance)允许子类型在泛型上下文中被安全地视为其父类型的实例,常见于只读数据结构中。通过在类型参数前添加out关键字,可声明该类型参数支持协变。
协变的语法定义
interface IProducer<out T>
{
    T Produce();
}
上述代码中,out T表示T仅作为方法返回值使用,不参与输入参数。这保证了类型安全性:若Dog是Animal的子类,则IProducer<Dog>可赋值给IProducer<Animal>。
类型安全机制分析
  • 协变仅适用于输出位置,防止将父类型实例写入子类型容器
  • 编译器静态检查确保协变类型参数不用于方法参数
  • 运行时无需额外开销,类型转换由CLR安全验证

2.2 接口与委托中的out关键字实践

在C#泛型编程中,`out`关键字用于协变(covariance),允许将派生类型的对象视为其基类型使用。这一特性在接口和委托中尤为重要。
协变接口定义
public interface IProducer<out T>
{
    T Produce();
}
此处 `out T` 表示 `T` 仅作为返回值使用,不可出现在参数位置。这使得 `IProducer<Dog>` 可隐式转换为 `IProducer<Animal>`,前提是 `Dog` 继承自 `Animal`。
委托中的协变应用
  • Func 是典型的协变委托
  • 支持将返回更具体类型的委托赋值给返回基类型的变量
例如:
Func<Dog> getDog = () => new Dog();
Func<Animal> getAnimal = getDog; // 协变支持
该机制提升了类型系统的灵活性,尤其适用于工厂模式与数据生产场景。

2.3 基于IEnumerable<T>的协变使用场景

在泛型接口中,`IEnumerable` 支持协变(covariance),允许将派生类型的集合视为其基类型集合。这一特性在处理多态数据时尤为实用。
协变的基本应用
当一个类继承自另一个类时,可利用协变实现接口的隐式转换:
class Animal { }
class Dog : Animal { }

IEnumerable<Dog> dogs = new List<Dog>();
IEnumerable<Animal> animals = dogs; // 协变支持
上述代码中,`IEnumerable` 被赋值给 `IEnumerable`,得益于 `out` 修饰的泛型参数 `T`,确保类型安全的同时提升灵活性。
实际应用场景
  • 统一处理不同子类型的集合,如遍历多种动物类型
  • 在API设计中返回更通用的枚举接口,增强可扩展性
  • 与LINQ结合使用,实现流畅的多态数据查询

2.4 协变在继承体系中的行为分析

协变(Covariance)允许子类型在继承体系中安全地替代父类型,尤其体现在返回值和泛型参数的使用上。
方法重写中的协变返回类型
Java 等语言支持协变返回类型,子类可重写方法并返回更具体的类型:

class Animal {}
class Dog extends Animal {}

class AnimalFactory {
    Animal create() { return new Animal(); }
}

class DogFactory extends AnimalFactory {
    @Override
    Dog create() { return new Dog(); } // 协变返回
}
上述代码中,DogFactory 重写 create() 方法,返回更具体的 Dog 类型,提升类型安全性与调用便利性。
泛型中的协变行为
通过通配符 ? extends T 实现泛型协变:
  • List<Dog> 可视为 List<? extends Animal>
  • 只允许读取为 Animal,禁止写入以保证类型安全

2.5 实战:构建支持协变的泛型组件

在泛型编程中,协变(Covariance)允许子类型关系在泛型容器中得以保留。例如,若 `Dog` 是 `Animal` 的子类,则希望 `List` 能被视为 `List`。
协变的类型约束实现
通过引入上界通配符或泛型类型参数约束,可实现协变行为:

type ReadOnlyContainer[+T any] struct {
    data []T
}

func (c *ReadOnlyContainer[T]) Get(index int) T {
    return c.data[index]
}
上述 Go 风格伪代码中,`+[T]` 表示类型参数 `T` 支持协变。这意味着 `ReadOnlyContainer[Dog]` 可赋值给 `ReadOnlyContainer[Animal]` 类型变量,前提是容器仅提供读取操作。
安全边界与限制
协变仅适用于只读场景。若组件支持写入,将破坏类型安全。因此,设计时需明确区分读写接口:
  • 只读泛型组件可安全协变
  • 可变组件应使用不变性(Invariance)
  • 生产者位置适合协变,消费者位置适合逆变

第三章:逆变(in)的原理剖析与典型用例

3.1 逆变的语言设计动机与语义解读

在类型系统中,逆变(Contravariance)主要用于函数参数的类型替换场景,其设计动机源于对多态安全性的保障。当子类型关系被反转时,逆变允许更灵活且类型安全的接口设计。
函数类型的逆变行为
考虑一个接受回调函数的场景:
type Printer func(string)
func ProcessJob(p Printer) {
    p("processing")
}
若存在 Printer 和更泛化的 AnyPrinter func(interface{}),直接传入会导致类型错误。但若将参数视为输入端,逆变允许用参数类型更宽的函数替代,因为其能处理原函数所期望的任何输入。
协变与逆变对比
位置协变逆变
返回值支持不安全
参数不安全支持
逆变确保:若 B 是 A 的子类型,则 func(A) 是 func(B) 的子类型,形成输入端的“反向继承”。

3.2 Action<T>与IComparer<T>中的逆变应用

在泛型接口中,逆变(contravariance)通过 `in` 关键字实现,允许更灵活的类型赋值。`Action` 和 `IComparer` 是逆变的经典应用场景。
逆变的基本原理
当接口参数仅作为输入时,可使用逆变。例如,`Action`,因为字符串是对象的子类。
Action stringAction = action; // 逆变支持
stringAction("Hello");

上述代码中,`Action`。尽管方法期望 `object`,但接收更具体的 `string` 类型是类型安全的。

IComparer 的逆变实践
`IComparer` 接口定义 `Compare(T x, T y)` 方法,参数为输入。这意味着可用于基类比较器处理子类对象。
  • 逆变提升代码复用性
  • 减少重复比较逻辑
  • 增强接口灵活性

3.3 逆变在参数输入场景中的优势体现

在函数式编程与泛型设计中,逆变(Contravariance)常用于参数输入场景,允许子类型更灵活地替换父类型。当方法接收一个参数时,若该参数位置支持逆变,则可接受更宽泛的类型输入。
逆变的典型应用场景
例如,在事件处理器或比较器接口中,期望接收基类的函数却能传入处理派生类的实现:

interface IComparer {
    int Compare(T x, T y);
}
此处 in T 表示泛型参数 T 是逆变的。这意味着 IComparer<Animal> 可被 IComparer<Dog> 替代,只要 Dog 继承自 Animal。
优势对比分析
  • 提升API复用性:通用比较逻辑无需为每个子类重复定义
  • 增强类型安全性:编译期检查确保输入合法
  • 降低耦合度:调用方关注行为而非具体类型

第四章:协变与逆变的综合对比与高级技巧

4.1 协变与逆变的本质区别与使用边界

协变(Covariance)与逆变(Contravariance)是类型系统中处理泛型子类型关系的核心机制。协变允许子类型替换,适用于只读场景;逆变则支持父类型替代,常见于参数输入。
协变的典型应用
type Reader interface {
    Read() string
}
type FileReader struct{}
func (f *FileReader) Read() string { return "file data" }

var r Reader = &FileReader{} // 协变:*FileReader 是 Reader 的子类型
此处接口赋值体现协变,Read() 方法仅输出数据,安全支持类型向上转换。
逆变的逻辑边界
在函数类型中,参数位置支持逆变:
  • 函数输入参数可接受更宽泛的类型(父类)
  • 返回值位置仅支持协变(更具体的子类)
位置支持变型示例
返回值协变func() Animal → func() Dog
参数逆变func(Animal) ← func(Dog)

4.2 同时使用in和out的泛型接口设计模式

在泛型编程中,同时使用 `in` 和 `out` 修饰符的接口被称为**协变与逆变共存**的设计模式。这种模式允许接口既作为数据生产者(`out T`),又作为消费者(`in T`),适用于复杂的数据转换场景。

协变与逆变的协同作用

当一个泛型接口需要同时支持返回泛型类型和接收泛型参数时,可定义如下:

public interface IProcessor<in T, out U>
{
    U Process(T input);
}
该接口中,`T` 为逆变参数(用于输入),`U` 为协变参数(用于输出)。这意味着 `IProcessor<Animal, Dog>` 可赋值给 `IProcessor<Cat, Animal>`,只要类型间存在继承关系。
  • in T:表示该类型仅用于方法参数,支持逆变;
  • out U:表示该类型仅用于返回值,支持协变。
此设计广泛应用于函数式接口和管道处理模型中,提升类型系统的灵活性与安全性。

4.3 类型转换异常与运行时行为预警

在强类型语言中,类型转换是常见操作,但不当的转换极易引发运行时异常。例如,在Go语言中将接口强制转换为不兼容类型时,会触发panic。
类型断言的安全模式
使用带双返回值的类型断言可有效避免程序崩溃:

value, ok := interfaceVar.(int)
if !ok {
    log.Println("类型转换失败:期望 int")
    return
}
上述代码中,ok布尔值用于判断转换是否成功,避免直接panic,提升系统健壮性。
常见异常场景对比
场景风险等级建议处理方式
空指针转型高前置nil检查
接口类型误判中使用ok-pattern安全断言

4.4 高效利用in/out提升API设计灵活性

在API设计中,合理使用输入(in)和输出(out)参数能够显著增强接口的可扩展性与调用方的控制力。通过分离数据流入与流出路径,系统职责更清晰,耦合度降低。
in/out参数的设计优势
  • in参数:用于传递调用上下文,如查询条件或配置选项;
  • out参数:明确返回结果结构,便于版本兼容与字段扩展;
  • 支持单入多出场景,例如批量操作的响应分组。
代码示例:Go语言中的in/out模式
type Request struct {
    UserID int `json:"user_id"`
}

type Response struct {
    Data  interface{} `json:"data"`
    Error string      `json:"error,omitempty"`
}

func GetUser(in *Request, out *Response) {
    user, err := fetchUser(in.UserID)
    if err != nil {
        out.Error = err.Error()
        return
    }
    out.Data = user
}
该函数接受in参数作为输入请求,通过out结构体返回结果,避免了直接返回值的局限性,便于中间件注入日志、监控等横切逻辑。

第五章:从理论到生产:协变逆变的最佳实践总结

接口设计中的类型安全控制
在定义泛型接口时,合理使用协变(out T)和逆变(in T)可提升API的灵活性。例如,对于只返回结果的查询服务,应声明为协变:

public interface IProducer<out T>
{
    T GetData();
}
这允许将 IProducer<Cat> 安全地赋值给 IProducer<Animal>。
事件处理与委托的逆变应用
.NET 中的事件常利用逆变简化订阅逻辑。如下示例中,基类参数的事件处理器可被用于子类事件:

public delegate void EventHandler<in TEventArgs>(object sender, TEventArgs e);
这意味着接受 EventArgs 的方法也能处理 CustomEventArgs 类型事件,降低重复注册。
常见误用场景与规避策略
  • 在可变集合接口中使用协变可能导致运行时异常,如 IEnumerable<out T> 合法,但 IList<out T> 不被允许
  • 避免在泛型方法参数中混合使用协变与逆变类型,除非明确理解其边界
  • 依赖注入容器注册时,注意服务契约的变体兼容性,防止解析失败
生产环境中的性能考量
模式内存开销调用速度适用场景
协变接口低高数据读取、工厂模式
逆变委托中中事件处理、策略模式
[EventSystem] → (EventHandler<in T>) → [BaseHandler] ↓ [CustomEvent] ──→ [BaseHandler.Execute()]
C#泛型协变与逆变:解决类型安全与灵活性的核心机制 在面向对象编程中,泛型是构建类型安全、可复用代码的重要机制。其核心原理在于通过类型参数化实现编译时类型检查,避免运行时错误。这一技术的核心价值在于平衡类型安全与代码灵活性,尤其在处理集合、委托和接口设计时至关重要。在实际应用场景中,开发者常遇到泛型类型转换问题,例如无法将IEnumerable<Derived>隐式转换为IEnumerable<Base>。这正是C#中协变与逆变机制要解决的核心问题——通过out和in关键字,在保证类型安全的前提下,允许泛型接口和委托在继承关系中进行特定方向的类型转换。理解协 阅读详情

相关推荐

CLR泛型底层原理:JIT实例化、约束验证与协变机制解析

泛型是.NET类型系统的核心机制,其本质并非语法糖,而是由CLR在运行时严格保障的类型契约。理解泛型需从IL元数据结构出发,掌握JIT如何为值类型和引用类型分别生成专用机器码,以及`where T : class/struct`等约束如何直接影响内存布局与方法分发路径。泛型协变与逆变并非类型转换,而是CLR对虚表调用链的拓扑重写,仅适用于接口和委托。技术价值体现在性能优化(如避免装箱)、内存控制(栈/堆分离)与类型安全强化;典型应用场景包括高性能集合库开发、DI容器泛型服务解析、序列化框架适配及AOT预编译

didi9310的博客 747

谈谈我对C#协变和逆变的理解

然后我们在程序中可以这么调用,我们用Person去接受一个Student,这是非常好理解的,从面向对象继承的角度来讲完全合理,因为我需要一个人Person,你给了我一个学生Student。注意这个委托的泛型T使用了out关键字,表示这个委托的参数T是支持协变的。这两个方法的声明和委托的声明保持一致。当然你应该看不懂这个公式,没关系,这边文章将会循序渐进的给大家介绍协变和逆变的概念,以及协变和逆变是为了解决什么问题。以上就是逆变的介绍,简单点说,就是将一个父类型的委托或者接口转换成子类型的委托或者接口。

曹瑞鹏的博客(专注于.NET开发,Unity开发) 2051

学习笔记:CNN中模型复杂度

CNN有卷积层和全连接层构成。对于一个卷积层,设输入通道数未CinC_{in}Cin​,输出通道数未CoutC_{out}Cout​,卷积核kernel size为Kw×KhK_w\times K_hKw​×Kh​,输出的特征图尺寸是H×WH\times WH×W 。全连接层的输入通道数为NinN_{in}Nin​,输出通道数为NoutN_{out}Nout​. 时间复杂度 用每秒钟浮点数运算量衡量。 FLOPs指的是floating-point operations per second,每秒钟浮点数运算

keep用心的博客 623

[C#] 重难点区分[In]、[Out]、in、out、in T、out T

重难点区分[In]、[Out]、in、out、in T、out T

mccoy39082的博客 3672

[官方培训]07-UE材质基础 孙丹璐 Epic 笔记

勾选允许自定义深度写入再在模型上勾选然后可以通过Scene Texture节点拿到渲染的自定义深度信息,有了自定义深度信息就可以与当前渲染的像素深度进行对比,自定义深度信息存放的是最靠近我们的深度,如果当前像素离自定义深度比较远我们就不要这个像素。效果如下这种方案的缺点也很明显,因为这样看不到第二层的透明了,如果是两层的半透明的裙摆,这样就看不到第二层的裙摆了。对于半透明排序问题最根本能解决的还是光线追踪,ue5中又加入了OIT(基于像素的排序)。官方透明材质的理解和应用。

Tcohneyn的博客 1562

知识抽取框架OneKE

OneKE 中指令的格式采用了类 JSON 字符串的结构,本质上是一种字典类型的字符串。优化知识抽取的性能不仅能够强化模型对世界知识的理解和应用,还能够构建知识要素之间的跨领域的深度关联和依赖,这些都是大规模知识图谱构建的关键依赖。一直是知识图谱大规模落地的关键难题之一,因为真实世界的信息高度碎片化、非结构化,大语言模型在处理信息抽取任务时仍因抽取内容与自然语言表述之间的巨大差异导致效果不佳,自然语言文本信息表达中因隐式、长距离上下文关联存在较多的歧义、多义、隐喻等,给知识抽取任务带来较大的挑战。

qq_32907491的博客 3207

C#泛型协变与逆变:类型安全与灵活性的核心机制

泛型是现代编程语言中实现代码复用和类型安全的核心特性。其原理在于通过类型参数化,在编译时进行类型检查,避免运行时错误。在面向对象编程中,子类型关系需要与泛型类型关系协调,这就引出了协变与逆变的概念。协变允许泛型类型参数随继承关系同向变化,仅用于输出位置,典型应用如IEnumerable<out T>,实现了集合的只读迭代安全。逆变则允许反向变化,仅用于输入位置,常见于委托和比较器接口如IComparer<in T>,支持更通用的处理逻辑。这两种机制在保持编译时类型安全的前提下,极大地提升了API的灵活性和表

weixin_34088583的博客 930

保姆级教程:用WorkVisual 6.0给你的KUKA机器人硬件做一次‘全身体检’与配置检查

本文详细介绍了如何使用WorkVisual 6.0对KUKA机器人进行全面的硬件诊断与配置检查。从环境准备到核心硬件模块检查,再到安全系统合规性验证,提供了保姆级教程,帮助技术团队快速掌握数字化诊断方案,提升工业机器人的健康管理效率。

weixin_27298377的博客 277

C#学习07 协变逆变_预处理指令_迭代器

(b)执行得到IEnumerator对象中的MoveNext方法,当返回值为true时,表示当前元素合法,并移动索引。(a)执行对象的 GetEnumerator()来获取迭代器IEnumertor。(2)#elif、#else 搭配 #if 使用,使用类似于条件语句。(1)#if 开始一个条件编译块,如果符号被定义则执行对应代码块。(1)#warning 生成编译器警告信息。(3)#endif 结束一个条件编译块。(1)#define 定义一个符号,(2)#undef取消定义一个符号。

2503_93931574的博客 867

七、从0开始卷出一个新项目之瑞萨RZN2L 2.2.2 启动模式和flash

七、从0开始卷出一个新项目之瑞萨RZN2L 2.2.2 启动模式和flash。

cl234583745的博客 1466

浙政钉H5应用上架实战:从环境配置到发布避坑指南

本文详细解析浙政钉H5应用上架全流程,从环境配置到发布避坑指南。重点介绍Vue 2.6 + Node 14.21.3的稳定开发环境搭建、项目结构规范及常见报错解决方案,帮助开发者高效完成浙政钉H5应用上架流程。

weixin_27943395的博客 286

C# 泛型协变与逆变

类型关键字转换方向适用位置协变out子类泛型 → 父类泛型返回值、集合读取逆变in父类泛型 → 子类泛型方法输入参数。

2401_84677775的博客 394

WSL2迁移后用户名不见了?一招教你快速恢复Ubuntu22.04默认用户

本文针对WSL2迁移后Ubuntu 22.04默认用户名丢失的常见问题,提供了详细的诊断与修复方案。通过分析迁移底层逻辑,指导用户使用`ubuntu2204.exe config --default-user`命令或配置`/etc/wsl.conf`文件快速恢复用户身份,并涵盖权限修复、冲突解决及自动化迁移脚本等进阶内容,确保子系统迁移后环境完整可用。

web39explorer的博客 558

【转】逆变与协变详解

逆变(contravariant)与协变(covariant)是C#4新增的概念,许多书籍和博客都有讲解,我觉得都没有把它们讲清楚,搞明白了它们,可以更准确地去定义泛型委托和接口,这里我尝试画图详细解析逆变与协变。 变的概念 我们都知道.Net里或者说在OO的世界里,可以安全地把子类的引用赋给父类引用,例如: 1 2 3 //父类 = 子类 stringstr = "string"; objectobj = str;//变了 ..

sinolover的专栏 535

斑马算法优化变分模态分解ZOA-VMD数字信号去噪(优化K值 alpha值)【含Matlab源码 4887期】

斑马算法优化变分模态分解ZOA-VMD数字信号去噪(优化K值 alpha值) 完整的代码,包运行;运行操作视频见优快云资源!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 811

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

第二阶段WinForm-7:文件操作补充,泛型复习,协变和逆变

(1)概念:泛型是C#2.0推出的新语法,它是专门为处理多段代码在不同的数据类型上执行相同的指令的情况而设计的。泛型让不同的数据支持相同的业务逻辑;泛型是一个符复合数据类, 把多个类型混合在一起使用,比如方法和泛型混到一起就是泛型方法, 类和泛型混合一起就是泛型类,接口和泛型混合到一起就是泛型接口List<T>, 如:List<int> ints = new List<int>(){10,11,12}(2)泛型定义语法格式<T>或<T,K,......> 其中T,K指未知类型。

m0_65011747的博客 693

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

泛型协变和逆变3

01.协变性指的是——泛型类型参数可以从一个派生类隐式转化为基类 在C#4.0中引入out关键字来标记泛型参数支持协变性 // List<T>.AddRange(IEnumerable<T>)方法 //将其元素添加到 List<T> 的末尾的集合。 集合自身不能为 null //但它可以包含为 null 的元素...

weixin_33950757的博客 153

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C#中协变逆变的实现

特性关键字方向适用场景协变out子类→父类返回值、集合遍历(如 IEnumerable<T>)逆变in父类→子类方法参数、回调处理(如 Action<T>)协变:out修饰的泛型替代符,只能作为返回值,不能作为参数逆变:in修饰的泛型替代符,只能作为参数,不能作为返回值协变:父类委托容器可以装 子类泛型委托容器逆变:子类委托容器可以装 父类泛型委托容器注意事项协变类型参数必须仅用于返回值位置。逆变类型参数必须仅用于方法参数位置。不支持类的协变/逆变,仅限接口和委托。

m0_74824496的博客 360

协变和逆变

转发:https://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html 背景知识:协变和逆变   假设有这样两个类型:TSub是TParent的子类,显然TSub型引用是可以安全转换为TParent型引用的。如果一个泛型接口IFoo<T>,IFoo<TSub>可以转换为IFoo<TParent>的话,我们称这个过程为协变,而且说这个泛型接口支持对T的协变。而如果一个泛型接口IB...

zhoumouren88的博客 255

协变逆变不变:泛型类型兼容性的三大交通规则

在静态类型语言中,协变、逆变与不变是泛型类型兼容性的核心原理,本质源于类型参数在‘产出位置’(如返回值、只读属性)与‘消耗位置’(如函数参数、可写字段)的安全传导逻辑。协变允许子类型安全替代父类型(如 IEnumerable<string> → IEnumerable<object>),逆变支持更宽泛参数类型被更具体类型满足(如 Action<object> ← Action<string>),而不变则是默认安全基线,防止双向操作引发的类型污染。这些规则直接决定API可复用性、泛型容器赋值合法性及跨语言类型

diedangxiang4092的博客 454

逆变与协变详解

我们都知道.Net里或者说在OO的世界里,可以安全地把子类的引用赋给父类引用,例如:123;object//变了而C#里又有泛型的概念,泛型是对类型系统的进一步抽象,比上面简单的类型高级,把上面的变化体现在泛型的参数上就是我们所说的逆变与协变的概念。通过在泛型参数上使用in或out关键字,可以得到逆变或协变的能力。

mb0v535ty的博客 200

揭秘C# 7.3泛型约束升级:5大应用场景让你的泛型更强大

掌握C# 7.3 泛型约束增强技巧,提升代码安全性与复用性。支持非托管、构造函数、比较器等5大应用场景,简化泛型类型限制,优化性能表现。深入解析新增约束关键字与实际案例,值得收藏。

DebugLoom的博客 654

那些年搞不懂的术语、概念:协变、逆变、不变体

协变性,如:string->object (子类到父类的转换)逆变性,如:object->string (父类到子类的转换)不变性,基于上面两种情况,不可变。具体下面再做分析。

PUQ263piG的博客 165

C# 关于泛型之协变逆变

C# 关于泛型之协变逆变

m0_37349899的博客 403

c#中关于协变性和逆变性(又叫抗变)帮助理解

今天回忆了之前看的《深入理解C#》这本书中的泛型章节,其中对泛型的可变性的理解。泛型可变性分两种:协变和逆变。逆变也又称为抗变。  怎么理解这两个名词的意思:   ①:协变即为在泛型接口类型中使用out标识的类型参数。协变的字面意思是“与变化的方向相同”②逆变那就是用in来标识的泛型接口类型的类型参数。逆变的字面意思是“与变化的方向相反”   需要注意的是无论是协变还是逆变也只能在泛型接口中...

GJQI12的专栏 319
上一篇: EF Core索引配置详解:如何用Fluent API实现精准性能调优
下一篇: 【Entity Framework Core批量删除性能优化】:揭秘高效删除百万级数据的5大核心技巧
CompiWander
博客等级 码龄1年 168粉丝 1980原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值