东亚银行、岚图汽车带你解锁 AIGC 时代的数字化人才培养各赛道新模式! 了解详情
写点什么

C# 7.1 先睹为快(第二部分)

  • 2017-06-12
  • 本文字数:1691 字

    阅读完需:约 6 分钟

天我们介绍了异步 Main 函数(Async Main)和默认表达式(Default Expressions)。我们的 C# 7.1 之旅将继续,今天要介绍的特性在建议中称为推导元组名(Infer Tuple Names)和使用泛型的模式匹配(Pattern-matching with Generics)。

推导元组名(Infer Tuple Names)

虽然开发人员不常考虑到,但是 C#中的匿名类型包括了命名推导。例如,编写如下代码时,对象 y 将具有名为 A 和 B 的属性:

复制代码
var y = new { x.A, x.B };

根据“推导元组名建议”,值元组基本具有同样的功能。

复制代码
var z1 = (A: x.A, B: x.B); // 显式名字。
var z2 = (x.A, x.B); // 推导名字。

但是匿名类型和值元组间存在着一些显著的差异:

  • 匿名类型需要属性名,属性明可以是显示指定的,也可以是推导得到的。
  • 值元组会将未命名属性标为 Item1、Item2 等。
  • 如果匿名类型具有重复的名字,那么会产生编译错误。
  • 如果值元组具有重复的显式名字,那么会产生编译错误。
  • 如果值元组具有重复的推导名字,那么推导名会被跳过。例如:(x.A, x.B, y.A) 将转化成 (Item1, B, Item3)。
  • 值元组不能使用如下保留名字:ToString、Rest、ItemN(N 是大于 0 的数字)。

C#和 VB 间有 hen 一个有意思的差别,VB 可以通过函数去推导匿名属性名。例如:

复制代码
var y = new { x.A, x.Bar() }; // 编译错误
Dim y = New With {x.A, x.Bar()} // 匿名类型{A,Bar}

该功能特性将扩展适用于 VB 元组。

但如果恰巧有一个扩展方法使用了与推导属性一样的名字,这一特性就会引发破坏性更改。在建议中进一步提出:

考虑到这一更改的破坏性有限,并且在 C# 7.0 中,交付元组的时间窗很短,兼容性委员会认为这种破坏性更改是可以接受的。

考虑泛型约束的元组名

如果存在元组名不匹配的问题,那么编译器会尽量警告编程人员。例如:

复制代码
public static (int A, int B) Test1((int A, int B) a)
Test1((A: 1, B: 2));
Test1((X: 1, Y: 2)); // 给出警告,元组名不匹配。

如果开始采用泛型约束,代码就不工作了:

复制代码
public static T Test2<t>(T a) where T : IEnumerable<(int A, int B)>
Test2(new List<(int A, int B)>());
Test2(new List<(int X, int Y)>()); // 没有警告。
</t>

当给出前的解释是,在泛型约束的条件下,编译器是不会去检查元组名的。理论上讲,编译器是可以捕获这类问题的,但是所付出的性能上的代价要远高于所得到的收益。

使用泛型的模式匹配

模式匹配是 C# 7.0 中新提供的特性。但是使用该特性时,存在设计上的缺陷。让我们看一下 Alex Wiese 给出的如下代码:

复制代码
class Program
{
static void Main(string[] args) {}
public void Send<t>(T packet) where T : Packet
{
if (packet is KeepalivePacket keepalive)
{
// 使用 keepalive 的功能代码。
}
switch (packet)
{
case KeepalivePacket keepalivePacket:
// 使用 keepalivePacket 的功能代码。
break;
}
}
}
public class Packet {}
public class KeepalivePacket : Packet {}
</t>

代码会报如下错误:“An expression of type T cannot be handled by a pattern of type KeepalivePacket.”。但如果我们将参数改为 System.Object 类型,而不是 T 类型,代码就工作正常了。

复制代码
public void Send(object packet)

C# 7.1,通过对引发模式匹配的规则进行微调,修正了这一问题。

我们改进了“模式匹配技术规范”中的一段内容,下面以粗体标出了我们所建议添加的内容:

我们认为左侧(left-hand-side)静态类型的特定组合与特定类型是不兼容的,这会导致编译时错误。我们称静态类型 E 的值与类型 T 是模式兼容的,如果存在标识转换(Identity Conversion)、隐式引用转换(Reference Conversion)、装箱转换(Boxing Conversion)、显式引用转换,或者存在从 E 到 T 的拆箱转换(Unboxing Conversion),或者 E 或 T 均为开放类型(Open Type)。如果具有类型 E 的表达式与其所匹配的类型模式中的类型并不模式兼容,就会产生编译时错误。

这被认为是一个软件问题修复问题。由于该更新是“向前不兼容”的,因此只有将编译器设为 C# 7.1,才能使用这一更新。

查看英文原文: An Early Look at C# 7.1: Part 2

2017-06-12 19:002175
用户头像

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

关注

评论

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

架构师实战营 模块一作业(微信业务架构和学生管理系统架构备选方案)

代廉洁

架构实战营

区块链开发主流语言和核心优势

CECBC

区块链

Redis 集群

escray

redis 学习 极客时间 Redis 核心技术与实战 4月日更

「Android渲染」为什么alpha渲染性能低?

李小四

Android渲染 Alpha 渲染

没有lrzsz,怎么传文件到服务器?

运维研习社

运维 工具

JavaScript 图片转文字,文字转语音

空城机

JavaScript 大前端 4月日更 tesseract 图片转文字

第13周课后练习-数据应用(二)

潘涛

架构师训练营 4 期

喂~ 办章吗?Python OpenCV 互联网+ 项目,图像处理取经之旅第 18 天

梦想橡皮擦

Python OpenCV 4月日更

架构实战营 模块一:课后作业

👈

架构实战营

Hadoop 3.x 版本相对于 Hadoop 2.x的新特性

五分钟学大数据

hadoop 4月日更

去面试,公司问我生辰八字。

yes

面试

架构实战营 模块 1 课后作业

eoeoeo

架构实战营

与JVM做朋友系列(2)再见类加载器

洛神灬殇

JVM ClassLoader 类加载器

如何在Deno中使用 Node 模块?

Sakura

4月日更

「架构师训练营 4 期」 第十三周 - 001&2

凯迪

架构师训练营 4 期

区块链:颠覆其外,守旧其中

CECBC

互联网

大数据计算生态之数据计算(二)

小舰

4月日更

Vue3源码 | 读懂keep-alive组件以及缓存机制

梁龙先森

源码分析 大前端 Vue3

外网访问Ubuntu下的Tomcat

U2647

tomcat ubuntu 4月日更

元数据管理—动态表单设计器在crudapi系统中完整实现

crudapi

API crud crudapi 动态表单 表单设计

如何做决策?

石云升

决策 28天写作 职场经验 管理经验 4月日更

华仔架构实战营 - 作业 - 模块1

曲元洪

架构实战营

博客主题用腻了?来试试赛博朋克 2077 主题吧!

清秋

CMS Hexo 博客 4月日更

【LeetCode】森林中的兔子Java题解

Albert

算法 LeetCode 4月日更

与JVM做朋友系列(3)又见Class字节码

洛神灬殇

JVM X86 stack register

架构实战营 模块一:学习总结

👈

架构实战营

区块链走红 江苏多行业应用迈入"可信时代"

CECBC

农产品

【极客大学】模块一作业

冬天的树

3.4 Go语言从入门到精通:包管理工具之Go module

xcbeyond

go modules Go 语言 4月日更

Netty 核心源码解读 —— EventLoop 篇

松然聊技术

回归本我还是追逐名利,技术人在中年危机下的抉择?

刘华Kenneth

管理 职场 中年危机

C# 7.1先睹为快(第二部分)_.NET_Jonathan Allen_InfoQ精选文章