写点什么

.NET 或将引入类型类和扩展

  • 2017-04-17
  • 本文字数:1919 字

    阅读完需:约 6 分钟

类型类是另外一项正被考虑引入.NET 未来版本的特性。在提案“外观和扩展( Shapes and Extensions )”中,该特性被称为外观,它们将大幅提升.NET 泛型的能力。Mads Torgersen 这样描述类型类:

接口抽象的是作为类型实例的对象和值的“外观(shape)”。从根本上讲,类型类背后的思想是抽象类型本身的外观。而且,当通过类型声明引入需要的类型实现一个接口时,其他人可以在单独的代码中实现类型类。

类型类解决了一个长期存在的接口问题:它们无法处理静态函数或操作符重载。这导致了一些问题,比如,在数学库中,对于不同的数值数据类型,需要反复声明相同的函数。

Mads 总结道:

一般来说,外观的声明和接口声明非常像,但它:

几乎可以定义任意类型的成员(包括静态成员)

可以通过扩展实现

可以在特定的地方像类型一样使用

最后一个限制很重要:外观不是类型。外观的主要目的是作为泛型的一种约束,限定类型参数,保证它们有正确的外观,并允许泛型声明体使用那个外观。

与外观的思想紧密相关的是一种经过改进的扩展语法。扩展结构几乎可以为类型类提供任何东西,而不只是方法扩展。考虑下面这个最简单的例子:

复制代码
public shape SNumber<T>
{
static T operator +(T t1, T t2);
static T operator -(T t1, T t2);
static T Zero { get; }
}

Int32 类型已经提供了大部分内容,但它缺少 zero 属性。扩展可以修复这个问题:

复制代码
public extension IntGroup of int : SNumber<int>
{
public static int Zero => 0;
}

然后,你可以像下面这样使用它:

复制代码
public static AddAll<T>(T[] ts) where T : SNumber<T> // shape 用作约束
{
var result = T.Zero; // 使用 shape 的 Zero 属性
foreach (var t in ts) { result += t; } // 使用 shape 的 + 操作符
return result;
}

实现

这实现起来需要一些接口和结构方面的技巧。

  • Shapes 被翻译成了接口,每个成员(甚至是静态成员)都转换成了接口中的实例成员;
  • 扩展被翻译成了结构,每个成员(甚至是静态成员)转换成了结构中的实例成员;
  • 如果扩展实现了一个或多个弯管,则底层的结构实现了那些外观的底层接口。

通常,上述结构被称为“见证结构(witness struct)”。它的存在可以证明一个类遵循外观的规则。或者换句话说,该类在类型类中。

编译器会将上述 AddAll 方法翻译成如下代码:

复制代码
public static T AddAll<T, Impl>(T[] ts) where Impl : struct, SNumber<T>
{
var impl = new Impl();
var result = impl.Zero;
foreach (var t in ts) { result = impl.op_Addition(result, t); }
return result;
}

然后,上述见证结构就可以用于向 AddAll 方法提供必要的功能。结构可以直接在类型上调用方法或者根据需要使用扩展结构。

在类和接口中实现外观

使用和我们扩展基类及实现接口一样的语法,类可以显式实现一个外观。然后,编译器会提供相应的见证结构。

也可以将接口标记为满足外观的要求。下面是一个例子:

复制代码
public extension Comparable<T> of IComparable<T> : SComparable<T> ;

由于 IComparable 和理论上的类型类之间存在一对一关系,所以我们不需要为扩展结构提供扩展体。

泛型类型

事实证明,泛型类型有他们自己的问题。和泛型方法一样,向泛型类添加外观或者类型类作为类型约束需要额外提供一个类型参数。在泛型类上,由于类型参数的数量是其名称的一部分,所以这会导致它和其它名称相同的泛型类型发生冲突。

扩展外观

扩展结构不仅可以用于实现外观,还可以扩展它们。因此,你可以向现有的外观中添加新方法、静态方法及操作符。正如扩展方法一样,语法是一样的,就像它们在底层类型上直接定义了一样。

评论

总的来说,人们对于该特性的反应不错。不过,也有一些修改请求。例如,外观目前必须显式实现。有些开发人员希望,如果特定的类或接口不需要额外扩展方法时,就由编译器隐式实现。Mads 列举了这样做的一些问题:

那可能会导致,为了见证以相同的方式应用到同一类型的同一个外观而生成许多结构类型,有生成的类型过度扩散的风险。如果编译器比较聪明,每个程序集只生成一个,或许可以缓解这种情况,但我们从匿名类型了解到,这种重复数据删除技术非常困难,而且很容易出错。

如果我们允许泛型类型拥有外观约束的类型参数,那么同一个东西拥有多个见证结构会导致实例化的泛型类型具有不同的类型标识,无法互换。

人们还担心外观和扩展绑定得太紧。他们认为,那将来可能会引起混淆。

对此,Mads 答复说:

合并:在我的提案里,“扩展”实际上合并了多个问题:

[……]

我觉得,对于上述服务于所有这些目的的语言机制,有太多内容需要讨论——但归根结底,它们的关系非常密切。如果有一个提案可以将它们清晰地分开,那将是非常有意义的。那也许会更加简单有效。

查看英文原文:.NET Futures: Type Classes and Extensions

2017-04-17 19:002179
用户头像

发布了 1008 篇内容, 共 412.0 次阅读, 收获喜欢 346 次。

关注

评论

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

中国人民大学周禹教授:数智人本主义-人力资源数智化驱动有质量增长

用友BIP

用友发布《大型企业项目数智化转型白皮书》

用友BIP

zone.js由入门到放弃之一——通过一场游戏认识zone.js

OpenTiny社区

前端 js

官宣定档!望繁信科技数聚·源力 2023 PRO_大会诚邀您参加!

ToB行业头条

企业为什么喜欢云桌面办公?

青椒云云电脑

桌面云 云桌面

云桌面落地六大秘籍

青椒云云电脑

云桌面

隐语小课|两方安全计算 ABY2.0 高效的 2PC 协议

隐语SecretFlow

大数据 AI 数据安全 隐私计算 开源社区

如何将IP定位SDK添加到您的 Android 应用程序

郑州埃文科技

软件 sdk

什么是云桌面?

青椒云云电脑

桌面云 云桌面

云桌面办公的三个优点

青椒云云电脑

桌面云 云桌面

亿级月活的社交APP,陌陌如何做到3分钟定位故障?

TakinTalks稳定性社区

数字孪生智慧粮仓Web3D可视化管理系统

2D3D前端可视化开发

智慧粮仓 智慧粮库 智慧粮仓管理系统 数字孪生粮仓 粮仓三维可视化

R语言之基本包

timerring

R 语言

云桌面五大优势,开启智慧校园云端新时代!

青椒云云电脑

桌面云 云桌面

阿里云 X 森马 AIGC T恤设计大赛开启! 穿什么由你定,赢Airpods,作品定制联名T恤

Serverless Devs

阿里云 Serverless 云原生

阿里云故障洞察提效50%,全栈可观测建设有哪些技术要点?

TakinTalks稳定性社区

Blender中有哪些有趣的插件

Finovy Cloud

blender Blender制作 Blender制作教程 Blender Apps blender软件资讯

公有云、私有云和混合云的云桌面有什么区别?

青椒云云电脑

桌面云 云桌面

Flink_state 的优化与 remote_state 的探索

Apache Flink

大数据 flink 实时计算

美团增量数仓建设新进展

Apache Flink

大数据 flink 实时计算

如何从用户视角搭建可观测体系?阿里云ECS业务团队的设计思路

TakinTalks稳定性社区

国内哪家云桌面厂家比较靠谱

青椒云云电脑

云桌面 云桌面厂家

云桌面系统解决方案

青椒云云电脑

云桌面 云桌面解决方案

基于静态编译构建微服务应用

阿里巴巴云原生

阿里云 云原生

云桌面如何工作?

青椒云云电脑

桌面云 云桌面

腾讯云升级发布新一代云数仓产品 CDW ClickHouse,万亿规模数据分析毫秒级响应

腾讯云大数据

数仓

零信任体系化能力建设(4):应用安全与开发部署

权说安全

零信任

.NET或将引入类型类和扩展_.NET_Jonathan Allen_InfoQ精选文章