C#逆变与协变

精通C#之逆变与协变 C#精通之路——逆变与协变 从C#4.0开始,泛型接口和泛型委托都支持协变和逆变,由于历史原因,数组也支持协变。 里氏替换原则:任何基类可以出现的地方,子类一定可以出现 协变(out) 协变:及自然的变化,遵循里氏替换原则,表现在代码上则是任何基类都可以被其子类赋值,如Animal = Dog、Animal = Cat 使用out关键字声明(注意和方法中修饰参数的out含义不同)。 被标记的参数类型只能作为方法的返回值(包括只读属性) 在没有协变时: abstract class Ani 阅读详情


C#中逆变与协变一般应用到以下三种场景

一、数组的协变
数组的协变允许派生程度更大的类型的数组隐式转换为派生程度更小的类型的数组。
比如:Object[] os = new String[5];

二、泛型接口的逆变与协变
    public class Program

    {

        static void Main(string[] args)

        {

            I<C2, C2> i = new U<C1, C3>();

        }

    }

    class C1{}

    class C2:C1{}

    class C3:C2{}

    interface I<in P, out R>

    {

        R Func(P p);

    }

    class U<P, R> : I< P, R>

    {

        public R Func(P p)

        {

            throw new NotImplementedException();

        }

}
上面的代码中,接口I同时应用了逆变和协变。
先说逆变:逆变允许 方法具有 与接口的泛型类型参数(实例中的 in P)所定义的参数类型(P作为Func的参数类型)相比,派生程度更大的返回类型。
在Main函数中,我们给定泛型接口I的类型参数中的R为C2,但实际的实现却是C1,并正常运行。为什么会发生这种情况呢?因为,
我们给定的参数类型是C2,也就是说变量i在其它调用者的眼里,含有一个参数类型为C2的方法Func,但i的骨子里却是用C1实现的,这样有何不可呢?
客户代码提供给i.Func的参数的类型是C2,而C2可以隐式转化为C1,一点也不影响使用。
再说协变,同样的道理,Func的返回值肯定是要用在适和C2类型的变量的地方,那么i.Func提供给客户代码一个C3类型的变量,又何乐不为呢?

三、委托的逆变和协变

对于普通委托:例如,
delegate C2 F1(C2 c);
F1 f1 = new U<C1, C3>().Func;
不需要说明什么,可以很自然地应用逆变与协变
但是对于泛型委托,例如,
delegate R F2<in P,out R>(P p);
F2<C2, C2> f2 = new U<C1, C3>().Func;

可以使用in和out关键字指定类型参数的逆变或协变,也可以不使用,两者没有什么区别。但需要注意的是,要么使用正确,要么不使用,否则会出现编译错误。
正确的作法是,在方法中作为参数的类型逆变,使用in关键字,作为返回值的类型协变,使用out关键字。

另外,还需要注意的是,当委托规定方法的参数有ref和out修饰时,该参数无法应用逆变,比如:
delegate C2 F0(ref C2 c);
F0 f0 = new U<C1, C3>().Func;//编译错误


C#中的协变逆变 文章目录一、C#中的协变二、C#中的逆变 一、C#中的协变 众所周知,子类对象可以赋值给父类,例如 string str = string.Empty; object obj = str; 不会报错。如果换一种方式,代码如下: public class Father { private string Name { get; set; } } public class Son : Father { private string Name { get; set; } } class Prog 阅读详情

相关推荐

C# 中的协变与逆变

在 C# 中,协变(Covariance)和逆变(Contravariance)是两个重要的概念,主要用于处理泛型类型参数的可变性。这两个概念允许在泛型类型之间进行更灵活的转换,提高了代码的可重用性和灵活性。协变允许将一个派生类型的泛型参数转换为基类型的泛型参数。简单来说,如果有两个泛型接口IFoo和IBar,并且IFoo的泛型参数T是协变的,那么如果A是B的派生类,就可以将IFoo转换为IFoo。逆变允许将一个基类型的泛型参数转换为派生类型的泛型参数。如果有两个泛型接口IFoo和IBar

2401_83367969的博客 2233

C#中的协变与逆变

一:什么是协变与逆变 协变指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,逆变指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型只有泛型接口和泛型委托参数支持协变和逆变 二:引言 using System; using System.Collections.Generic; class MainClass { static void Main() { object o = "str"; List<object&g.

L的博客 5426

ANSYS-CFX,计算时报错,内存参数报错,return code 1【终极解决方案】

ANSYS-CFX,计算时报错,内存参数报错,return code 1【终极解决方案】 在CFX计算时经常会遇到内存不足的错误报告,有的算例网格并不多也会出现这样的问题,本文就最近遇到的内存错误问题以及解决方法进行简单的总结,以供大家参考。 1 CFX-Solver Manager内存种类 打开Define Run,面板上的Partitioner、Solver、Interpolator选项中分别都有关于内存的设置选项。当出现内存不足错误时,应该设置哪一个选项的内存参数,要看是哪一部分的内存不足。 2 C

深海民工CFDer 3万+

深入理解C#的协变和逆变及其限制原因

本篇文章的主题:变体(Variance),上面的object[] objArray = strArray形式被称为协变,此外还有另一种变体形式被称为逆变(一些书籍或文章翻译为抗变)。 变体的主要形式包括协变(Covariance)和逆变(Contravariance),后面我会使用What-Why-How的方式逐个说明这两个概念。

fjjaylz的博客 2602

西门子S7-1200与汇川SV660F伺服Profinet通讯调试实战

在工业自动化领域,Profinet作为工业以太网标准协议,凭借其高实时性和灵活组网能力,已成为伺服驱动器与PLC通讯的主流选择。其核心原理是通过设备名识别、IP分配以及标准报文(如111速度报文、105定位报文)传输控制字与状态字,实现驱动器的精准控制。相比传统脉冲或CANOpen方案,Profinet直连省去了协议转换网关,降低了成本与故障点,尤其适用于绕线设备、包装机械等中小型单轴或多轴运动控制系统。本文以西门子S7-1200 PLC搭配汇川SV660F伺服为例,完整梳理了从GSDMD组态、InoDri

weixin_29184371的博客 227

Codesys电子凸轮功能块MC_CamIn的masteroffset和slaveoffset参数的使用

问题1:在Codesys使用作轴电子凸轮时,MC_CamTableSelect的参数设置为MasterAbsolute=1,SlaveAbsolute=1,此设置为绝得模式, 此时主从轴当前位置都不为零时,此时Masteroffset=0、slaveOffset=0,凸轮启时出现突变,实轴无法启动。问题分析:在觉得模式下,主轴位置和从轴为是对应凸轮表的相位的,Masteroffset=0、slaveOffset=0,启动点时在主轴位置=0,从轴位置=0的点启动,此时主轴当前位置不为零则主从轴位置发生突变,

weixin_43587371的博客 1801

C#进阶-协变与逆变

C#中的逆变和协变是一组强大的泛型特性,它们为我们在处理泛型委托和泛型接口时提供了更灵活、更安全的类型转换机制。本文将深入讨论逆变和协变的语法和用法,并通过具体的示例代码进行演示。

踏雨歌青春,诗酒趁年华 2580

CZT与FFT频谱分析方法对比:从任意频带重采样到高精度频谱分析

M = 85 % 输出点数f0 = 70 Hz % 起始频率DELF = 0.4 Hz % 频率步长频率分辨率提高到0.4 Hz分析带宽聚焦在[70, 103.6]Hz更清晰地分辨出78Hz和82Hz的频率分量。

2403_88098319的博客 1860

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

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

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

Python Trimesh库实战:5分钟搞定STL文件解析与3D模型可视化

本文介绍了如何使用Python的Trimesh库快速解析STL文件并进行3D模型可视化。通过简洁的代码示例,演示了从环境搭建、模型加载、几何数据提取到基础变换和批量处理的核心流程,帮助开发者和工程师在5分钟内高效完成3D数据处理与可视化任务。

weixin_32005771的博客 160

小新学习K8s第一天之K8s基础概念

kubernetes是一个可移植,可扩展的开源平台,用于管理容器化工作负载和服务,有助于声明式配置和自动化。它拥有庞大且快速发展的生态系统。kubernetes服务,支持和工具随处可见。作用:用于自动部署,扩展和管理“容器化应用程序”的开源系统。可以理解成k8s是负责自动化运维管理多个容器化程序(比如docker)的集群,是一个生态及其丰富的容器编排框架工具。

pangdongqiqi的博客 1228

C#协变和逆变

协变(covariant)和逆变(contravariant)是C#4.0新增的概念。 首先,我们都知道C#中父类可以充当子类来使用,就像我们在泛型中说到的object是所有类型的父类,那么以下变量赋值时不会报错的: string str = string.Empty; object obj = str; 但是如果换一种方式来表达:  创建一个Human类: using System; usin...

kun_wang的博客 1973

深度剖析XY2-100与SL2-100协议:解锁激光打标核心技术密码

XY2-100和SL2-100是激光打标领域的两种核心控制协议。XY2-100协议采用串行通信,指令集简单,适合常规打标任务,具有成本优势;SL2-100协议支持更高速率(1Mbps以上),具备曲线插补等高级指令,在精密加工领域表现突出。两者的主要差异体现在数据传输(帧结构、速率)、指令集(功能、数量)、参数调节(范围、精度)和错误处理机制等方面。实际应用中,XY2-100适合简单图形的大批量生产,SL2-100更胜任复杂曲面的高精度加工。选择时需综合考虑打标需求、设备兼容性和成本因素,未来两种协议将持续优

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 957

C# 泛型中的协变和逆变

💎协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,后者指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型。泛型类型参数支持协变和逆变,可在分配和使用泛型类型方面提供更大的灵活性。在引用类型系统时,协变、逆变和不变性具有如下定义。这些示例假定一个名为Base的基类和一个名为Derived的派生类。Covariance使你能够使用比原始指定的类型派生程度更大的类型。你可以将的实例分配给类型的变量。

李赛赛的专栏 1719

lammps教程:非晶sio2建模方法

大家好,我是小马老师。 本文介绍非晶sio2的建模方法。 sio2的建模方法有很多,可以下载cif文件使用atomsk转为data文件,也可以直接在ms中导入sio2结构,这些方法建的sio2都是标准的sio2晶体。 如果要建立非晶状态的sio2,就是把排列规则的sio2变成无序排列的sio2。 非晶建模方法有很多,在lammps中,可以通过高温高压的方法打乱sio2的排列实现非晶建模。 代码中的温度和步数可根据需要自己调整。 下面给出in文件案例代码。 units metal atom

lammps_jiayou的博客 5268

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

图解C#高级教程(四):协变、逆变

本章的主题是可变性(variance),这里的可变性更多的是指基类和派生类之间的转换。可变性分为三种:协变(covariance)、逆变(contravariance)和不变(invariance)。

聚焦C++/Python编程语言、大模型应用开发 2698

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C# 泛型(协变和逆变)

纵观本章,大家已经看到了,如果你创建泛型类型的实例,编译器会接受泛型类型声明以及类型实参来创建构造类型。但是,大家通常会犯的一个错误就是将派生类型的委托分配给基类型委托的变量。下面来看一下这个主题,这叫作可变性(variance)。它分为三种一一一协变(convariance)、逆变(contravariance)和不变(invariance)。

钢铁男儿 1186

OV9734 DATASHEET,完整规格书

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

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C# 泛型的协变与逆变

那么先讲讲什么是“泛型类协变”你可以这样理解,正常的变换 好比object = String 这样的表达式一样协变主要是向上安全的变换,但是需要根据继承链条一层一层 的向上变化 而不需要进行转换因为是隐式转换,先上一层继承类的代码 不过使 用最容易的理解的,你认为是拆箱与装箱也没什么太大的出入 但是指泛型上的

3922

C#中的协变和逆变

C#从2.0开始推出了泛型,极大的简化了相同算法对应不同数据类型的工作。在此基础上,C#4.0更进一步推出了泛型中的协变和逆变,有不少人对这个概念感觉比较模糊,今天就让我们来简单的捋一捋。 最常见的情况 考虑下面代码 object[] objs = new string[]{}; List&amp;lt;object&amp;gt; objList = new List&amp;lt;string&amp;gt;(); 这段代...

君子务本 2743

C# 逆变与协变

该文章中使用了较多的 委托delegate和Lambda表达式,如果你并不熟悉这些,请查看我的文章《委托与匿名委托》、《匿名委托与Lambda表达式》以便帮你建立完整的知识体系。 在C#从诞生到发展壮大的过程中,新知识点不断引入。逆变与协变并不是C#独创的,属于后续引入。在Java中同样存在逆变与协变,后续我还会写一篇Java逆变协变的文章,有兴趣的朋友可以关注一下。 逆变与协变,听起来很抽象、高深,其实很简单。看下面的代码: class Person { } clas

dreamgis的专栏 477

C# 逆变和协变详解

协变是指在泛型类型的使用中,允许将某个类型参数替换为该参数的派生类(即更具体的类型)。换句话说,协变允许在泛型委托或接口中使用更具体的类型作为返回类型。

学习和分享 1023

C#进阶学习(十二)协变逆变

本文简单介绍了C#中协变与逆变的相关知识点。

FAREWELL00075的博客 1079

C# 协变、逆变 看完这篇就懂了

原标题:C# 协变、逆变 看完这篇就懂了 转自:Virgil-Zhou cnblogs.com/VVStudy/p/11404300.html 一、基本概念 官方:协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,后者指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型。 公式: 协变:IFoo<父类> = IFoo<子类>; 逆变:IBar<子类> = IBar<父类>; 暂时不理解没关系,您接着往下看。

qq_37390527的博客 1425

C# 中的协变和逆变

作为一个从接触 Unity 3D 才开始学习 C# 的人,我一直只了解一些最基本、最简单的语言特性。最近看了《C# in Depth》这本书,发现这里面东西还真不少,即使除去和 Windows 编程相关的内容,只是兼容 Unity 的部分就够好好消化一阵子的。其中,令我非常头大的一组概念,就是协变性和逆变性(统称可变性)。 一、可变性的概念 C# 一开始就支持数组的协变,听说是为了和 Java

加菲教主的技术专栏 975

c#: 协变和逆变深度解析

环境:window 10.netcore 3.1vs2019 16.5.1一、为什么要有协变?首先看下面的代码:还有下面的:其实上面报错的是同一个问题,就是你无法用List<Fru...

dotNET跨平台 582
上一篇: C#访问权限
下一篇: 常用SQL语句整理(一)
lcprogram
博客等级 码龄15年 2粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值