首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C# | 泛型委托的协变与逆变

协变 协变: 当类型参数仅用作输出(即返回值)时,可将类型参数标记为 out 这样就允许 Del dogMaker = MakeDog; // MakeDog是一个返回Dog匹配委托的方法...期望返回 Animal , 而其指向的 Del 返回了 Dog , Dog 是 Animal 的派生类,接受返回 Dog ,于是可以,调用代码可以自由的操作返回的对象的 Animal 部分 逆变...逆变: 当类型参数仅用作输入(作为方法的参数类型),可将类型参数标记为in 这样就允许 Del animal =ActOnAnimal; // ActOnAnimal为匹配此委托的方法...于是又传入了其指向了 Del , 于是传入 Del 了一个Animal的派生类Dog 这种在期望传入基类 时允许传入派生对象 的特性叫做逆变...本文作者: yiyun 本文链接: https://moeci.com/posts/2022/01/CSharp-泛型委托的协变与逆变/ 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA

63920

C#泛型的逆变协变之个人理解

一般来说, 泛型的作用就类似一个占位符, 或者说是一个参数, 可以让我们把类型像参数一样进行传递, 尽可能地复用代码。...泛型里的逆变协变了 Q:   细嗦细嗦 逆变协变 C#泛型中的逆变(in)协变(out)对于不常自定义泛型的开发来说(可能)是个很难理解的概念, 简单来说其表现形式如下 逆变(in): I =..., 与协变相似, 需要在泛型 T 之前加上关键词 in 对比上方的协变, 逆变看起来就像是将基类赋值给子类, 但这其实符合里氏代换的 当我们调用 item.Print 时, 看起来允许传入的参数为 string...类型, 而实际上最终调用的 Face.Print 是支持 object 的, 传入 string 类型的参数没有任何问题 逆变协变的作用 逆变(in)协变(out)的作用就是扩展泛型的用法...A:   简单来说, 有关泛型输入的用逆变, 关键词是in, 有关泛型输出的用协变, 关键词是out, 如果接口中既有输入又有输出, 就不能用逆变协变 Q:   为什么这两个不能同时存在?

20120
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【Kotlin】泛型 ③ ( 泛型 out 协变 | 泛型 in 逆变 | 泛型 invariant 不变 | 泛型逆变协变代码示例 | 使用 reified 关键字检查泛型参数类型 )

    文章目录 一、泛型 out 协变 二、泛型 in 逆变 三、泛型 invariant 不变 四、泛型逆变协变代码示例 五、使用 reified 关键字检查泛型参数类型 本章总结 : 使用了 泛型 out...协变 和 泛型 in 逆变 极大的提高了程序的扩展性 ; 泛型 in 逆变 : 使用 in 关键字 , 可以使 父类泛型对象 赋值给 子类泛型对象 ; 泛型 out 协变 : 使用 out 关键字 ,...可以使 子类泛型对象 赋值给 父类泛型对象 ; 一、泛型 out 协变 ---- 使用 out 关键字 , 可以使 子类泛型对象 赋值给 父类泛型对象 ; 在 泛型类 中 , 如果只将 泛型类型...又用于作为参数 ; interface ProducerOrConsumer { fun produce(): T fun consume(t: T) } 四、泛型逆变协变代码示例...( 反之就会报错 ) 如果 使用 out 关键字 , 则 范围小的子类泛型对象 赋值给 范围大的 父类泛型对象 ; ( 反之就会报错 ) 使用了 泛型 out 协变 和 泛型 in 逆变 极大的提高了程序的扩展性

    1.8K10

    泛型协变与抗变(二)

    前言   在.NET 4之前,泛型接口是不变的。.NET 4通过协变和抗变为泛型接口和泛型委托添加了一个重要的扩展。协变和抗变指对参数和返回值的类型进行转换。   ...这里就比较接近泛型接口的协变和抗变的概念了。...理解泛型接口的协变和抗变(in、out)   我们下面来看看泛型接口的协变及抗变的例子:   首先我们看下协变,在C#高级编程(第十一版)中指出,如果泛型类型用out关键字标注,泛型接口就是协变的。...在C#高级编程中指出的概念:如果泛型类型用in关键字标注,泛型接口就是抗变的。这样,接口只能把泛型类型T用作其方法的输入。  ...总结   其实在上述例子及其概念中,我们可以发现,泛型接口的协变及抗变,也就是将类型参数返回或者传入的情况,在这情况下进行其类型的隐式转换所遵循的规律。

    82020

    Java泛型的协变和逆变

    背景 文接上回,说到过Java的泛型擦除问题,这块我又联想到一个有意思的考点泛型的协变和逆变。...一、协变 首先Java的数组是协变的,所以假设A是B的父类,那么A[]是可以保存A或者B的对象的,并且A[]是B[]的父类。 ,写谁都会写,子类型限定。...根因是Java的泛型没有协变类型,无法关联起来,也就没有关系。 利用通配符,?代表子类,T为父类。 常见的例子比如,List协变,消费者为逆变。 针对于生产者,可取,有上界;针对于消费者,可存,有下界。...小结 1、协变、逆变的区别要分清 2、另外,再提一点泛型和通配符的区别,当然也可以结合第一点理解, 用于定义泛型类和方法,擦除后为AAA类型; <?

    72600

    Java泛型的协变与逆变

    导读 泛型是Java最基础的语法之一,众所周知:出于安全原因,泛型默认不能支持型变(否则会引入危险),因此Java提供了通配符上限和通配符下限来支持型变,其中通配符上限就泛型协变,通配符下限就是泛型逆变...协变:通配符上限 为了让泛型支持型变,Java引入了通配符上限语法:如果A是B的子类,那么List相当于是List的子类——这种型变方式被称为协变(covariance)。 对于支持协变的泛型集合,例如List泛型来说,对于支持协变的泛型,程序只能调用以泛型为返回值类型的方法;不能调用形参为泛型的方法。例如如下代码。...extends Number>也是支持协变的泛型,因此该类型的变量只能调用返回值为泛型的方法,不能调用形参为泛型的方法——如上①号代码所示。

    1.3K40

    Java泛型的协变和逆变

    背景 文接上回,说到过Java的泛型擦除问题,这块我又联想到一个有意思的考点泛型的协变和逆变。...一、协变 首先Java的数组是协变的,所以假设A是B的父类,那么A[]是可以保存A或者B的对象的,并且A[]是B[]的父类。 ,写谁都会写,子类型限定。...根因是Java的泛型没有协变类型,无法关联起来,也就没有关系。 利用通配符,?代表子类,T为父类。 常见的例子比如,List协变,消费者为逆变。 针对于生产者,可取,有上界;针对于消费者,可存,有下界。...小结 1、协变、逆变的区别要分清。 2、另外,再提一点泛型和通配符的区别,当然也可以结合第一点理解, 用于定义泛型类和方法,擦除后为AAA类型; <?

    54350

    iOS 泛型 ObjectType 协变 __covariant 逆变 __contravariant

    泛型使用场景: 在集合(数组、字典、NSSet)中使用泛型比较常见。 当声明一个类,类里面的某些属性的类型不确定,这时候我们才使用泛型。...泛型书写规范 在类型后面定义泛型: NSMutableArray *datas 泛型好处: 提高开发规范,减少程序员之间交流 通过集合取出来对象,直接当做泛型对象使用,可以直接使用点语法...__covariant(协变):用于泛型数据强转类型,可以向上强转,子类可以转成父类。 __contravariant(逆变):用于泛型数据强转类型,可以向下强转,父类可以转成子类。...例如: // __covariant 协变,子类转父类;泛型名字是ObjectType @interface Person :NSObject // 语言...} 添加了逆变 // __contravariant 可以逆变,父类转子类 泛型名字是ObjectType @interface Person<__contravariant ObjectType

    3.5K40

    iOS_泛型 Generics __covariant(协变) __contravariant(逆变)

    文章目录 1、泛型 `Generics` 2、`__kindof` 类型限制 3、自定义泛型 4、协变 和 逆变 4.1、`__covariant`协变 4.2、`__contravariant`逆变...4.2、系统类举例 1、泛型 Generics 泛型可以让你使用自定义的类型来编写灵活的、可重用的函数和类型,可以避免重复,以清晰、抽象的方式表达其意图。...__covariant(协变)或__contravariant(逆变)来控制转换关系。...(详情见下文) 4、协变 和 逆变 介绍协变和逆变前,先回顾一下:subtype、supertype: subtype、supertype是面向对象开发中最常见的类型关系,即子类型和父类型。...名词解释: variant: 即型变 co + varian: 共同变化,即协变的(con: 共同) contra + variant:逆变,抗变(contra: 相反;对立面) 例:有父类Person

    1K10

    【Kotlin】泛型总结 ★ ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 | 可变参数结合泛型 | out 协变 | in 逆变 | reified 检查泛型参数类型 )

    文章目录 一、泛型类 二、泛型参数 三、泛型函数 四、多泛型参数 五、泛型类型约束 六、可变参数 vararg 关键字与泛型结合使用 七、使用 [] 运算符获取指定可变参数对象 八、泛型 out 协变...九、泛型 in 逆变 十、泛型 invariant 不变 十一、泛型逆变协变代码示例 十二、使用 reified 关键字检查泛型参数类型 一、泛型类 ---- 定义一个 泛型类 , 将 泛型参数 T...八、泛型 out 协变 ---- 使用 out 关键字 , 可以使 子类泛型对象 赋值给 父类泛型对象 ; 在 泛型类 中 , 如果只将 泛型类型 作为 函数的返回值 类型 , 则在 声明 泛型参数... { fun produce(): T fun consume(t: T) } 十一、泛型逆变协变代码示例 ---- 泛型类 中 泛型参数 有 子类 和 父类 , Java 语言中...( 反之就会报错 ) 如果 使用 out 关键字 , 则 范围小的子类泛型对象 赋值给 范围大的 父类泛型对象 ; ( 反之就会报错 ) 使用了 泛型 out 协变 和 泛型 in 逆变 极大的提高了程序的扩展性

    4.1K10

    C#高级语法之泛型、泛型约束,类型安全、逆变和协变(思想原理)

    编译也可以通过 IAnimalHouse dogHouse = new AnimalHouse(); IAnimalHouse animalHouse = dogHouse; 协变的作用就是可以将子类泛型隐式转换为父类泛型...,而逆变就是将父类泛型隐式转换为子类泛型 将接口类型改为使用in关键字 public interface IAnimalHouse where T : Animal,new() { } 逆变就完成了...:协变时泛型无法作为参数、逆变时泛型无法作为返回值。...思考:那么,现在你能明白上面那个错误,为什么“协变时泛型无法作为参数、逆变时泛型无法作为返回值”了吗?...TestOut方法返回的是一个Dog类型的对象 //所以当我们在AddAnimal()中传入new Animal()时,会存在Animal父类到Dog子类的转换 //类型是不安全的,所以协变时泛型无法作为参数

    7.1K30

    【JAVA冷知识】什么是逆变(contravariant)&协变(covariant)?数组支持协变&逆变吗?泛型呢?

    写在前面 ---- 和小伙伴分享一些java小知识点,主要围绕下面几点: 什么是逆变(contravariant)&协变(covariant)? 数组支持协变&逆变吗? 泛型支持协变&逆变吗?...,不支持逆变,那泛型呢?...对于协变和逆变是否支持 泛型不支持协变也不支持逆变,即不能把一个父类对象赋值给一个子类类型变量,相反也是同理。...所以直接编译报错,即泛型不支持协变也不支持逆变....,在运行期为一个具体的值.编译没有报错 Process finished with exit code 0 逆变同样也是可以,即泛型可以通过super和extends来模拟实现协变和逆变,但是本身是不存在协变和逆变的

    70710

    C#4.0新增功能03 泛型中的协变和逆变

    泛型类型参数支持协变和逆变,可在分配和使用泛型类型方面提供更大的灵活性。 在引用类型系统时,协变、逆变和不变性具有如下定义。...泛型委托的类型参数中的协方差和逆变的效果类似于普通委托绑定中的协方差和逆变的效果(请参阅委托中的差异 (C#) 和委托中的差异 (Visual Basic))。....NET Framework 4 开始,Visual Basic 和 C# 提供了一些关键字,利用这些关键字,可以将接口和委托的泛型类型参数标记为协变或逆变。...Visual Basic 和 C# 不允许违反协变和逆变类型参数的使用规则,也不允许将协变和逆变批注添加到接口和委托类型之外的类型参数中。...有关信息和示例代码,请参阅泛型接口中的差异 (C#) 和泛型接口中的差异 (Visual Basic)。

    1.3K20

    C#协变和逆变

    直白的理解:  “协变”->”和谐的变”->”很自然的变化”->string->object :协变。  “逆变”->”逆常的变”->”不正常的变化”->object->string 逆变。 ...我个人的理解: 因为协变和逆变的英文太复杂了,并没有体现协变和逆变的不同,但是out 和 in 却很直白。...out: 输出(作为结果),in:输入(作为参数) 所以如果有一个泛型参数标记为out,则代表它是用来输出的,只能作为结果返回,而如果有一个泛型参数标记为in,则代表它是用来输入的,也就是它只能作为参数...想要回答这个问题需要在回头看看Clr via C# 关于泛型和接口的章节了,我就不解释了,  答案是不可以。  上面演示的是协变,接下来要演示下逆变。 ...In 关键字:逆变,代表输入,代表着只能被使用,不能作为返回值,所以C#编译器可以根据in关键字推断这个泛型类型只能被使用,所以Action actionDog = actionAnimal;

    95130

    Kotlin 范型之协变、逆变

    型变 型变是指类型转换后的继承关系。 Kotlin 的型变分为逆变、协变和不变。...2.1 协变 如果 A 是 B 的子类型,并且Generic 也是 Generic 的子类型,那么 Generic 可以称之为一个协变类。...下面的代码因为是协变的,无法添加新的对象。编译器只能知道类型是 Animal 的子类,并不能确定具体类型是什么,因此无法验证类型的安全性。 List<?...2.3 不变 默认情况下,Kotlin 中的泛型类是不变的。 这意味着它们既不是协变的也不是逆变的。 例如 MutableList,它可读可写,泛型没有使用in、out。 三....总结 本文从 Kotlin 的类、类型引出了型变。介绍了 Kotlin 的协变、协变和不变的概念和特性,以及 Java 的上界通配符、下界通配符。 该系列的相关文章: Kotlin 泛型之类型擦除

    1.3K50

    Kotlin泛型的型变之路

    但是这种处理在我们处理泛型业务时,会有很多限制,所以,泛型提供了「型变」来拓展泛型的使用。 协变 协变指的是,当参数具有父子关系时,子类可以作为参数传递,而泛型的上界就是其父类。...所以,经过协变之后的泛型,就失去了写入的能力,它只能用于向外提供数据,也就是「数据生产者Producer」。 逆变 逆变指的是,父类可以作为参数传递,但子类必须是其下界。逆变通过下界通配符可以使泛型支持协变,但是「只能读不能写」,这里的写,指的是对泛型集合添加元素,如果是remove(int index)或者是clear这种删除,则不受影响。 泛型通配符泛型之后,我们再来看下Kotlin的泛型,这时候你再看,就没那么复杂了,核心就两条。 使用关键字 out 来支持协变,等同于 Java 中的上界通配符 ?...那么我们在实际的代码中,要在哪些场景使用协变和逆变呢?通常来说,泛型参数协变后则表示——「这个参数在当前类中,只能作为函数的返回值,或者是只读属性」。

    1.2K21

    C#泛型入门泛型类、泛型集合、泛型方法、泛型约束、泛型委托

    .NET/C#面试手册:基础语法 .NET/C#面试手册:面向对象 .NET/C#面试手册:集合、异常、泛型、LINQ、委托、EF!...: 《.NET/C#面试手册》包含[基础知识]、[面向对象]、[集合、异常、泛型、LINQ、委托、EF]、[ASP.NET MVC]、[ASP.NET Core]、[ADO.NET、XML、HTTP...《.NET/C#面试手册》完整pdf、word下载地址 ###本章阅读列表### 泛型很难理解?...不然 泛型集合和ArrayList的装箱拆箱 常见的泛型类型 泛型类和泛型方法 泛型约束 泛型委托 ###泛型很难理解?...第一次接触泛型那还是在大二上学期的时候,那会是学c#面向对象的时候接触过泛型集合,但尴尬的是那会还没有“泛型”这个概念,仅仅只停留在泛型集合的使用。

    2.6K30

    C# 泛型

    1、泛型的优势 在日常开发中,我们经常会开发一些特殊的功能,而这个功能适用于多个类型(比如string,int等多种类型),最简单的做法是给每种类型都做一个实现,这种做法的缺点是代码冗余,无疑增加了我们的工作量...最好的方法是使用泛型,.NET自从2.0开始支持泛型,它不仅是编程语言的一部分,而且与程序集中间语言IL紧密结合。...以下是泛型的优点 (1)、通过泛型我们不必给不同的类型编写功能相同的许多方法或类,只创建一个方泛型方法或泛型类即可。...(2)、通过泛型,我们可以创建独立于被包含的类型的类和方法 (3)、泛型类的泛型类型可以根据需要进行替换,保证了类型的安全性。注:如何传入的类型不支持泛型类,那么编译器就会报错。  ...这个后面会提到泛型约束的问题! (4)、泛型不仅限于类,而且适用于接口和方法 (5)、泛型

    661100
    领券