2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

未来的 C#之覆写放宽

  • 2017-05-02
  • 本文字数:1259 字

    阅读完需:约 4 分钟

能使用协变(covariant)返回类型,这是一个在.NET 中常被请求到的特性。例如,可以使用“override Widget Clone()”覆写“virtual object Clone()”。从类型安全的角度看,这种做法完全可以接受,但是当前并不被 C#所允许。

根据“对协变返回类型的建议”,该规则将被放宽,使得相比于基类中的方法,子类中的同一方法可以返回更具体的类型。除了上例中给出的 Clone 方法之外,这种放宽对抽象工厂和其他框架代码也会十分有用。

隐式投影(Implicit Shadowing) 在 C#中,一种可能的实现方法是发射(Emit)两个函数。还以 Clone 方法为例,我们可以在中间语言(IL)中看到如下的方法签名(Method Signature):

复制代码
override object Clonable.Clone()
public new Widget Clone()

按 HaloFour 的说法,这是可以工作的,原因在于:

在通用语言运行库(CLR,Common Language Runtime)规范中,看上去的确允许覆写具有不同的名字,并可以具有不同的可见性(Visibility)。

[…]

通过在 IL 中显式地使用“.override”语句,我能解决所有的重载决议(Overload Resolution)问题,并能使用具有不同可见性和名字的方法进行覆写。

该编译器特性可与现有的 CLR 版本无缝工作,并且旧版本的 VB 或 C#将可以毫无问题地消费这样的类。

但是这一做法也存在着一些限制。首先,从覆写方法正常继承而来的属性是不能被拷贝到隐藏(New)方法中的。从技术上讲,编译器可以拷贝基类属性到隐藏方法上。但是这种做法存在着问题,一旦添加隐藏属性添加到基类方法,就将需要对子类进行重编译。

其次,这也会导致在使用反射(Reflection)时,难以看到隐藏方法与被覆写的基类方法之间的关联。

最后一点,这会对通过基类接口的调用方法产生性能上的影响。但是,该问题可以通过尾调用(Tail Call)及其他优化技术缓解。

属性

在 C#中,另一种可能的实现方法是使用新属性。如果编译器能识别该属性,则会针对更具体的类型自动添加强制转换(Cast)。

该方法的一个缺点在于,如果新属性不能被语言所理解,就不能使用该方法。当然,新属性也必须添加到基础类库(BLC,Base Class Library)中,这意味着它不会在所有的平台上立刻可用。

另一个缺点是,它可能会在处理结构体时引入不必要的装箱(Boxing)操作。继续以上面的 Clone 方法为例,编译器将必须装箱一个 WidgerStruct 结构体,然后立刻将其强制转换为一个正常的 WidgetStruct 结构体。

投影和覆写的放宽

另一种替代做法是放宽对投影的限制规则。当前,一个方法是不允许同时被投影和覆写的。但是,考虑到 CLR 是支持这种做法的,C#只是允许显式地编写如下代码:

复制代码
class Widget : Cloneable
{
public override Cloneable Clone()
{
return this.Clone();
}
public new Widget Clone()
{
return [...];
}
}

根据隐式投影的建议,这将依赖编译器去重命名重载方法。

时间表

需要指出的是,大部分该特性相关的讨论出现于 2015 年上半年,即两年之前。但是该建议是在今年二月份才正式写完,因此尚未采取任何行动,或者说尚未公开采取任何行动。

查看英文原文: C# Futures: Relaxed Overrides

2017-05-02 19:001945
用户头像

发布了 227 篇内容, 共 84.9 次阅读, 收获喜欢 28 次。

关注

评论

发布
暂无评论
发现更多内容

vue自定义指令

小恺

6月月更

一文读懂Logstash原理

恒山其若陋兮

6月月更

思科私有动态路由协议:EIGRP

wljslmz

动态路由 6月月更 路由协议 EIGRP

BottomSheetDialog 使用详解,设置圆角、固定高度、默认全屏等

yechaoa

android dialog 6月月更 material design

ConcurrentHashMap 源码分析-put方法

zarmnosaj

6月月更

LabVIEW控制Arduino实现红外测距(进阶篇—6)

不脱发的程序猿

单片机 LabVIEW VISA Arduino Uno 红外测距

什么是Vue3的组合式 API?

源字节1号

软件开发 小程序开发

模块八作业

库尔斯

#架构实战营

为什么需要微服务

阿泽🧸

微服务 6月月更

消息队列存储消息数据的 MySQL表

Dean.Zhang

【Python技能树共建】lxml 模块

梦想橡皮擦

Python 6月月更

预解析与作用域

Jason199

js 全局作用域 作用域 6月月更

谈谈远程工作 | 社区征文

大菠萝

初夏征文

向线程池提交任务

急需上岸的小谢

6月月更

volatile的解构

卢卡多多

volatile 6月月更

RF中使用reuqests的两种方式

红毛丹

Python 6月月更

flutter系列之:flutter中常用的container layout详解

程序那些事

flutter 程序那些事 6月月更

WWDC22 开发者需要关注的重点内容

37手游iOS技术运营团队

iOS16 WWDC22 Xcode14 iPadOS16 macOS10.16

基于华为云图像识别标签实战

乌龟哥哥

6月月更

数据库每日一题---第9天:销售员

知心宝贝

数据库 算法 前端 后端 6月月更

消息队列入门MQ

卢卡多多

MQ 消息队列 6月月更

5分钟了解攻防演练中的红蓝紫

穿过生命散发芬芳

6月月更 攻防演练

Flutter doctor 显示xcode没有安装的解决办法

坚果

6月月更

动态规划之0-1背包问题(详解+分析+原码)

未见花闻

6月月更

leetcode 257. Binary Tree Paths 二叉树的所有路径(简单)

okokabcd

LeetCode 搜索 数据结构与算法

【Spring 学习笔记(十)】Spring 使用注解整合 Mybatis

倔强的牛角

Java spring Java EE 6月月更

LabVIEW控制Arduino实现超声波测距(进阶篇—5)

不脱发的程序猿

单片机 LabVIEW Arduino VISA 超声波测距

LabVIEW Arduino电子称重系统(项目篇—1)

不脱发的程序猿

单片机 LabVIEW VISA ​Arduino Uno 电子称重系统

【愚公系列】2022年06月 面向对象设计原则(六)-合成复用原则

愚公搬代码

6月月更

直播预告|FeatureStore Meetup V3 重磅来袭!

星策开源社区

机器学习 开源 DevOps 特征平台 MLOps

Java—并发容器

武师叔

6月月更

未来的C#之覆写放宽_.NET_Jonathan Allen_InfoQ精选文章