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

c#4.0中的不变(invariant)、协变(covariant)、逆变(contravariant)小记

园子里已经有不少高手撰文写过这个话题:比如“装配脑袋”的NET 4.0中的泛型协变和反变 (2008年他就已经搞明白了这个概念)、偶像Artech的“C# 4.0新特性-"协变"与"逆变"以及背后的编程思想...” 以及1-2-3的 协变(Covariance)和逆变(Contravariance)的十万个为什么 这里只是从应用的角度,简单记录一下: 从.net3.5开始,System命名空间里就定义了一个泛型委托... 说得更白一点,4.0以前的泛型委托,泛型参数一旦在实例使用过程中明确为具体类型后,是不能隐式自动转换成其它类型的,哪怕类型是兼容的(按道理来讲,fn1...,所以返回类型ArgumentException可以向上的转化为Exception不会有任何问题,所以说fn1中的参数类型与fn2中的参数类型是安全兼容的,但是编译回不允许),这种不允许泛型参数类型变化的特点...记忆方法:向上转型称协变(因为这种转型肯定是安全的,比较“和谐”),向下转型称逆变(因为不一定能转型成功,有出错的可能,称逆变) 最后:in,out这二个关键字不仅能用于泛型委托,同样也适用于泛型接口(

864100

金三银四面试:C#.NET面试题中高级篇3,含答案解析

sample.SampleShow(); } Console.ReadKey(); } (2)as 不仅负责检查兼容性还会进行类型转换,并返回结果,如果不兼容则返回...而.NET委托完全不同,委托是类型安全的类,它定义了返回类型和参数的类型。委托类不仅包含对方法的引用,也可以包含对多个方法的引用。---->详解7.在.NET中可以自定义委托吗?...public delegate void Feedback(int num); 理解委托的一个要点是它们的安全性非常高。在定义委托时,必须给出它所表示的方法的签名和返回类型等全部细节。...(Object sender, TEventArgs e)where TEventArgs : EventArgs; 4).使用获取泛型实参和返回值的委托时,可利用逆变与协变。...逆变:父类转换为子类;协变:子类转换为父类 ---->详解 10. 什么是匿名方法? 匿名方法是用作委托的参数的一段代码。

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

    .Neter所应该彻底了解的委托

    委托究竟是什么? 委托究竟是用来干嘛的? 委托跟匿名函数的区别? 委托与事件的关系?...: 首先函数指针就是一个内存地址,指向函数的入口内存地址 当函数指针做一个函数的参数时,确实会起到一定解耦作用 函数指针很明显是类型不安全的 我们再来声明和使用委托: public delegate int...有兴趣的朋友可以去了解事件的原理,也是很有趣 最后的最后,我们还要谈下委托的一个功能: 委托的参数逆变和返回值的协变 由于委托也支持泛型委托,因此我们可以看看微软定义好的 public delegate...void Action(T obj);//其中in表示逆变 public delegate TResult Func();//其中out表示协变 class Program...I am Func 想要了解更深的朋友可以去了解泛型的协变和逆变,在这里就不深入探讨了

    41120

    30分钟泛型教程

    ,我们不希望在使用类型的时候就指定T的类型 我们希望在使用这个类型的方法时,再指定T的类型 来看看如下代码: public class MyClass { public...但你可以先把T转化成object再把object转化成你要的类型(一般不推荐这么做,你应该考虑把T转化成一个约束兼容的类型) 你也可以考虑用as操作符进行类型转化,这一般不会报错,但只能转化成引用类型。...十、逆变和协变  一般情况下,我们使用泛型时,由T标记的泛型类型是不能更改的 也就是说,如下两种写法都是错误的 var a = new List(); List b =...协变: 泛型类型T可以从派生类型更改为它的基类型, 用out关键字来标记协变形式的类型参数, 而且这个参数一般作为返回值 如果我们定义了一个这样的委托: public delegate TResult...注意: 只有接口和委托的泛型类型才可以使用逆变和协变的特性 参考资料 Mgen的博客 CLR VIA C#(第三版)

    73260

    C#规范整理·泛型委托事件

    委托本身是一种引用类型,它保存的也是托管堆中对象的引用,只不过这个引用比较特殊,它是对方法的引用。事件本身也是委托,它是委托组,C#中提供了关键字event来对事件进行特别区分。   ...11.使用泛型参数兼容泛型接口的不可变性# 让返回值类型返回比声明的类型派生程度更大的类型,就是“协变”。...“T”为协变。 12.让接口中的泛型参数支持协变# 除了11中提到的使用泛型参数兼容泛型接口的不可变性外,还有一种办法就是为接口中的泛型声明加上out关键字来支持协变。...13.理解委托中的协变# 委托中的泛型变量天然是部分支持协变的。...# 逆变是指方法的参数可以是委托或泛型接口的参数类型的基类。

    27830

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

    泛型类型参数支持协变和逆变,可在分配和使用泛型类型方面提供更大的灵活性。 在引用类型系统时,协变、逆变和不变性具有如下定义。...始终可以将此实参安全地传递给基础方法,因为该方法的形参属于类型 Base。 通常,协变类型参数可用作委托的返回类型,而逆变类型参数可用作参数类型。...向 Circle 中添加新 SortedSet对象时,每次将新元素与现有元素进行比较时,都会调用 IComparer.Compare 对象的IComparer(Of Shape...但不能将协变类型参数用作接口方法的泛型类型约束。 如果接口的方法具有泛型委托类型的参数,则接口类型的协变类型参数可用于指定委托类型的逆变类型参数。...Visual Basic 和 C# 不允许违反协变和逆变类型参数的使用规则,也不允许将协变和逆变批注添加到接口和委托类型之外的类型参数中。

    1.3K20

    .NET面试题系列 - 泛型

    “可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用。“ - Jon Skeet 泛型 泛型相比反射,委托等较为抽象的概念要更接地气得多,而且在平常工作时,我们几乎时刻都和泛型有接触。...例如对普通继承中的可变性:若某方法声明返回类型为Stream,在实现时可以返回一个MemoryStream。可变性有两种类型:协变和逆变。...这也告诉我们,逆变性是很不正常的。 泛型的协变与逆变 协变性和out关键字搭配使用,用于向调用者返回某项操作的值。例如下面的接口仅有一个方法,就是生产一个T类型的实例。那么我们可以传入一个特定类型。...使用in和out表示可变性 如果类型参数用于输出,就使用out,如果用于输入,就使用in。注意,协变和逆变性体现在泛型类T和T的派生类。目前out 和in 关键字只能在接口和委托中使用。...协变与逆变的相互作用 以下的代码中,接口IBar中有一个方法,其接受另一个接口IFoo作为参数。IFoo是支持协变的。这样会出现一个问题。

    72730

    了解C#的协变和逆变

    前言 在引用类型系统时,协变、逆变和不变性具有如下定义。 这些示例假定一个名为 Base 的基类和一个名为 Derived的派生类。...: 兼容性:.NET2.0就推出了泛型,而从.NET 2.0到.NET 3.5期间不支持对泛型接口中的占位符T支持隐式转换,因此在.NET4.0推出协变和逆变 为了支持更广泛的隐式类型的转换,在这里就是在泛型体系中支持...,有下面的约束,否则则会在编译时报错: 泛型参数占位符以out关键子标识,并且占位符T只能用于只读属性、方法或者委托的返回值,out简而易懂,就是输出的意思 当要进行类型转换,占位符T要转换的目标类型也必须是其基类...、方法或者委托的输入参数 当要进行类型转换,占位符T要转换的目标类型也必须是其子类,上述例子则是FooBase转为Foo 总结 协变和逆变只对泛型委托和泛型接口有效,对普通的泛型类和泛型方法无效 协变和逆变的类型必须是引用类型...,因为值类型不具备继承性,因此类型转换存在不兼容性 泛型接口和泛型委托可同时存在协变和逆变的类型参数,即占位符T 参考 泛型中的协变和逆变 | Microsoft Docs 《你必须知道的.NET(第2

    94810

    C#2.0新增功能06 协变和逆变

    在 C# 中,协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。 协变保留分配兼容性,逆变则与之相反。 以下代码演示分配兼容性、协变和逆变之间的差异。 // 分配兼容性....// 分配兼容性被反转. Action actString = actObject; 对方法组的协变和逆变支持允许将方法签名与委托类型相匹配。...这样,不仅可以将具有匹配签名的方法分配给委托,还可以分配与委托类型指定的派生类型相比,返回派生程度更大的类型的方法(协变)或接受具有派生程度更小的类型的参数的方法(逆变)。...有关详细信息,请参阅委托中的变体 (C#) 和使用委托中的变体 (C#)。 以下代码示例演示对方法组的协变和逆变支持。...使用委托中的变体 (C#) 演示如何使用非泛型委托中的协变和逆变支持以将方法签名与委托类型相匹配。

    1K10

    编写高质量代码改善C#程序的157个建议

    本文主要学习记录以下内容:   建议42、使用泛型参数兼容泛型接口的不可变性   建议43、让接口中的泛型参数支持协变   建议44、理解委托中的协变   建议45、为泛型类型参数指定协变 建议42、...使用泛型参数兼容泛型接口的不可变性 让返回值类型返回比声明的类型派生程度更大的类型,就是“协变”。...实际上,只要泛型类型参数在一个接口声明中不被用来作为方法的输入参数,我们都可姑且把它堪称是“返回值”类型的。所以,本建议中这种模式是满足“协变”的定义的。...建议44、理解委托中的协变 委托中的泛型变量天然是部分支持协变的。为什么说是“部分支持协变”呢?... 逆变是指方法的参数可以是委托或泛型接口的参数类型的基类。

    33530

    认真CS☀️协变、逆变 & 不变

    >类了,无法赋值给同级别的Factory类),而是直接将它的引用MakeDog赋值给animal,这是可行的 2、我们还有一种方法,那就是协变(在类型参数前加out)(派生类只是用来输出值...) “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。...“协变”->”和谐的变”->”很自然的变化”->string->object :协变 协变在委托声明中加入out关键字,表示派生类只是用来输出值,避免出现由delegate派生类是平级,它们定义的变量无法相互赋值产生的问题...,方法期望的只是其基类,方法完全可以像以前那样操作对象的基类部分 “逆变”则是指能够使用派生程度更小的类型。...因此变化只是用于引用类型,不能从值类型派生其他类型 b、显式变化使用in和out关键字只适用于委托和接口,不适用于类、结构和方法 c、不包括in、out关键字的委托和接口类型参数叫不变。

    10210

    C#委托

    假如在写游戏,有一个人物,他会升级,那么在他升级的时候,需要给他添加潜力值,而判断升级是经验类需要写的。 先写一个经验类。 核心 如果当前经验大于最大经验,升级。...这时可以使用委托。 如果当前经验大于最大经验 调用函数升级 那么函数 升级 如何让人物知道,可以使用一个委托 升级 调用委托 于是人物可以添加函数到经验。...如果使用的委托是 多播,那么小心用 BeginInvoke 如果使用 同步,那么多个方法是可以运行 static void Main(string[] args)...需要转类型,定义是知道他是什么类型,上面使用的是 Action ,所以可以转 Action ,如果是自定义的,那么使用自定义的。...如果委托发生异常 如果委托方法里没有 try catch,那么如果使用 invoke, 委托是函数指针链,所以会在执行异常退出。

    40630

    C#基础篇——泛型

    可以创建:泛型接口、泛型类、泛型方法、泛型事件和泛型委托 开始 泛型类 泛型类封装不特定于特定数据类型的操作。泛型类最常见用法是用于链接列表、哈希表、堆栈、队列和树等集合。...: Stack s = new Stack(); Stack.StackDelegate myDelegate = StackNotify; 泛型委托在定义基于典型设计模式的事件时特别有用...可以看到,在泛型接口的T前面有一个out关键字修饰,而且T只能是返回值类型,不能作为参数类型,这就是协变。使用了协变以后,左边声明的是基类,右边可以声明基类或者基类的子类。...协变除了可以用在接口上面,也可以用在委托上面: Func func = new Func(() => null); 除了使用.NET框架定义好的以为,我们还可以自定义协变,...MyList();//逆变+协变 有关可变性的注意事项 变化只适用于引用类型,因为不能直接从值类型派生其他类型 显示变化使用in和out关键字只适用于委托和接口,不适用于类、

    1.3K40

    C#委托 如果委托发生异常事件

    假如在写游戏,有一个人物,他会升级,那么在他升级的时候,需要给他添加潜力值,而判断升级是经验类需要写的。 先写一个经验类。 核心 如果当前经验大于最大经验,升级。...这时可以使用委托。 如果当前经验大于最大经验 调用函数升级 那么函数 升级 如何让人物知道,可以使用一个委托 升级 调用委托 于是人物可以添加函数到经验。...如果使用的委托是 多播,那么小心用 BeginInvoke 如果使用 同步,那么多个方法是可以运行 static void Main(string[] args)...需要转类型,定义是知道他是什么类型,上面使用的是 Action ,所以可以转 Action ,如果是自定义的,那么使用自定义的。...如果委托发生异常 如果委托方法里没有 try catch,那么如果使用 invoke, 委托是函数指针链,所以会在执行异常退出。

    1.4K20

    C# 4.0新特性-协变与逆变以及背后的编程思想

    ,我们就可以这样的定义协变和逆变:如果类型TBar是基于强类型Bar的类型(比如类型参数为Bar的泛型类型,或者是参数/返回值类型为Bar的委托),而类型TFoo是基于弱类型Foo的类型,协变就是将TBar...二、委托中的协变与逆变的使用 协变和逆变主要体现在两个地方:接口和委托,先来看看在委托中如何使用协变和逆变。...现在我们定义了如下一个表示无参函数的泛型委托Function,类型参数为函数返回值的类型。泛型参数之前添加了一个out关键字表示T是一个协变变体。...下面定义了一个名称为Operate的泛型委托,接受一个具有泛型参数类型的参数。在定义泛型参数前添加了in关键字,表示T是一个基于逆变的变体。...将契约的观点应用在委托上面,委托实际上定义了一个方法的签名(参数列表和返回值),那么参数和返回值的类型就是契约,现在的关键是谁去履行这份契约。

    63880

    不惧面试:委托

    3.委托能用来做什么?★☆ 本题主要考察委托在我们写code时的用途。一个笼统的准则:当要把方法传给其他方法时,需要使用委托。...向一个方法中传递一个子类的方法。   c.事件。     一般通知代码发生了什么事件。GUI编程主要处理事件。在引发事件时,运行库需要知道应执行哪个方法。     ...这就需要处理事件的方法作为一个参数传递给委托。 4.如何自定义委托★☆ 声明一个委托类型,它的实例引用一个方法,该方法获取一个int参数,返回void。...,可利用逆变与协变。...逆变:父类转换为子类;协变:子类转换为父类 9.什么事匿名方法★★ 匿名方法是用作委托的参数的一段代码。

    824141

    C# 发展历史及版本新功能介绍

    到达迭代器方法的结尾时,循环便已完成。 协变和逆变 在 C# 中,协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。 协变保留分配兼容性,逆变则与之相反。...以下代码演示分配兼容性、协变和逆变之间的差异。 // Assignment compatibility....泛型协变和逆变 协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,后者指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型。...泛型类型参数支持协变和逆变,可在分配和使用泛型类型方面提供更大的灵活性。 在引用类型系统时,协变、逆变和不变性具有如下定义。...后续版本的 C# 偶尔会向依赖项添加新类型或成员。

    4.2K20

    C#学习笔记七: C#4.0中微小改动-可选参数,泛型的可变性

    可选参数重在"可选", 即在调用方法时, 该参数可以明确指定实参, 也可以不指定实参.如下代码: 1 class Program 2 { 3 static void Main() 4...这就是可选参数的好用之处, 特别是对于一个系统的后期维护很好使用, 在真实的项目中我也使用过这样的用法, 如下例: 在我们做的系统中切换User有SwitchUser(不lougout当前user,然后添加新的...这里的解决方案就是仍然使用同一个Check方法,但是给这个Check方法新添加一个可选参数来判断到底是执行的哪个操作, 然后根据不同的操作去做相应的修改....类型. 2.3协变和逆变的注意事项 (1)只有接口和委托才支持协变和逆变, 类或泛型方法的类型参数都不支持协变和逆变 (2)协变和逆变只适用于引用类型, 值类型不支持协变和逆变(例如List无法转化为...IEnumerable) (3)必须显式地用in或out来标记类型参数 (4)委托的可变性不要再多播委托中使用 3,动态类型 在C#4.0中, 微软引入了dynamic管家你来定义动态类型

    1.4K80

    List与List的区别何在

    换句话来说,使用泛型类不带尖括号、具体类型的用法,其实是一种妥协:为了与早期程序的兼容。 也就是说:对于现在写的程序,谁要是使用泛型类时不填写具体类型,都应该打屁股哦。...注意 现在使用泛型类时,都应该为泛型指定具体的类型。 为了保持与早期程序兼容,Java允许在使用泛型类时不传入具体类型的搞法,被称为”原始类型(raw type)“。...②号代码处向list集合添加String类型的元素。...那么问题来了,②号代码处是否可以向list集合(其实是List集合)添加String类型的元素呢? 如果你不运行这个程序,你能得到正确答案吗? 答案是:完全可以添加进去!...>变量,此时的本质就是泛型协变。 由于List代表元素不确定类型的List集合,因此程序无法向 List<?

    1.7K20

    C#进阶-协变与逆变

    协变与逆变 协变(共变):泛型委托或泛型接口的类似于父类转向子类的变换; 逆变(反变):泛型委托或泛型接口的类似子类到父类的隐式转换; 逆变与协变用来描述类型转换后的继承关系,其定义:如果A、B表示类型...,f(x)表示类型转换,≤表示继承关系(比如,A≤B表示A是由B派生出来的子类) 当A≤B时,若f(x)是逆变的,则f(B)≤f(A)成立; 当A≤B时,若f(x)是协变的,则f(A)≤f(B)成立;...,和string与Object的父子关系是相反的; 协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。...InterfaceFuncObject = InterfaceFuncInt;//编译失败,值类型不参与协变或逆变 //泛型接口-逆变 InterfaceFuncB变 //数组的协变使派生程度更大的类型的数组能够隐式转换为派生程度更小的类型的数组。

    13721
    领券