写点什么

.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:002507
用户头像

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

关注

评论

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

拒绝"通灵式调试":用AI重构代码的"尸检报告"

HuiZhuDev

软件工程 研发效能 代码调试 Prompt Engineering AI辅助编程

ava 王者修炼手册【Mysql 篇 - 事务】:吃透 ACID 本质 + 隔离级别底层 + 大事务排查优化方案,掌控事务核心逻辑

DonaldCen

ACID 实现原理 隔离级别底层机制 大事务识别优化

区块链 Web3 外包开发上线流程

北京木奇移动技术有限公司

区块链开发 软件外包公司 web3开发

Java 王者修炼手册【基础篇-异常机制】:Java异常的底层逻辑

DonaldCen

异常底层原理 深入理解异常 异常表 异常最佳实践

Java 王者修炼手册【基础篇-反射机制】:反射让底层操控力直接拉满!

DonaldCen

Class类用法 Constructor类用法 Field用法 Method用法

Java 王者修炼手册【JVM篇 - 底层原理】:从类加载到 JVM 调优与 OOM 诊断修炼

DonaldCen

JVM GC算法 双亲委派模型 垃圾回收器

Java 王者修炼手册【Spring 篇 - 循环依赖 & 三级缓存】:Bean创建流程 + 循环依赖 + 三级缓存原理 大揭秘

DonaldCen

循环依赖 三级缓存 Bean创建流程

Java 王者修炼手册【Mysql篇 - SQL执行存储流程】:拆解 InnoDB 存储结构与 SQL 执行流程,吃透 Buffer Pool 和 Change Buffer 核心原理

DonaldCen

Buffer Pool 数据存储机制 Change Buffer SQL 各子句的执行顺序

BeeWorks Meet:一款支持私有化内网使用的视频会议软件

BeeWorks

即时通讯 IM 私有化部署

Java 王者修炼手册【集合篇-HashMap】:HashMap 核心技能 + HashSet 搭档机制全拆解

DonaldCen

HashMap底层原理 HashSet HashMap扩容机制

Java 王者修炼手册【集合篇-ConcurrentHashMap】 :从分段锁到桶级锁的锁系进化

DonaldCen

ConcurrentHashMap 并发

Java 王者修炼手册【并发篇-并发基础】:从线程状态到同步机制的底层修炼

DonaldCen

线程安全 线程状态 线程协作

Java王者修炼手册【Spring 篇 - Bean核心原理】:从 Bean 定义注册到动态代理全链路修炼

DonaldCen

bean FactoryBean JDK 动态代理 CGLIB 动态代理 ObjectFactory

ava 王者修炼手册【Spring 篇 - AOP 与事务】:底层原理 + 实战避坑全攻略

DonaldCen

AOP 核心 AOP 底层流程 AOP失效场景 Spring 事务

Java 王者修炼手册【Mysql 篇 - 大表操作】:千万级大表核心操作原理与实战方案

DonaldCen

数据模型与操作 大表删除字段 大表清除数据 大表新增字段

Java 王者修炼手册【Mysql篇 - 索引+ SQL优化】:拆解 索引 + 执行计划 + SQL优化 核心原理

DonaldCen

B+树 覆盖索引 索引下推 索引合并 索引失效场景

Java 王者修炼手册【MyBatis 篇 - 底层依赖】:吃透 JDBC/MyBatis 核心接口类,掌控全链路整合逻辑

DonaldCen

connection SqlSessionTemplate BoundSql PreparedStatement

CAD怎么添加打印文件PC5

极客天地

Java 王者修炼手册【基础篇-泛型机制】:从底层原理到实战应用,核心知识点与面试考点全涵盖

DonaldCen

泛型 java基础 类型擦除

Java 王者修炼手册【集合篇-ArrayList】:从ArrayList数据结构到避坑指南

DonaldCen

线程安全 ArrayList linkedlist 扩容机制

Java 王者修炼手册【并发篇 - 并发工具】:从 AQS到线程池修炼

DonaldCen

AQS ReentrantLock Condition LockSupport 同步工具

Java 王者修炼手册【Mysql 篇 - 日志】:吃透 MySQL redo log + undo log + binlog 底层机制

DonaldCen

Binlog Redo Log Undo Log 两阶段提交 WAL核心原理

Java 王者修炼手册【Mysql 篇 - 锁】:吃透 MySQL 行锁 + 间隙锁 + 意向锁 底层机制,了解死锁解决方案

DonaldCen

死锁 间隙锁 意向锁 行锁

千万 QPS 下的 DNS 治理:从“够用”到“可控”

柯杰

架构 后端 网络

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