QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

C# 7 特性预览

  • 2016-04-06
  • 本文字数:3009 字

    阅读完需:约 10 分钟

在过去一年间,我们为读者展示了多个已考虑加入C# 7 中的特性。在最近发布的Visual Studio 15 预览版中,微软决定为用户展现这些特性,使其成为C# 7 最终发布的一部分。

元组值类型

.NET 提供了一个元组(Tuple)类型,但具体在C#中使用时却存在着各种各样的问题。由于元组类型是一个引用类型,因此在一些对于性能相当敏感的代码中,你很可能会避免因使用它而造成GC 的开销。同时,元组类型是不可变的,虽然这使跨线程共享变得更安全,但也意味着每次进行变更都必须分配一个新的对象。

为了应对这一问题,C# 7 将提供一个值类型的元组。这是一个可变类型,对那些重视性能的代码来说,这种方式将更为高效。同时,作为值类型,它在每次进行分配时都会生成一个拷贝,因此几乎没有产生多线程问题的风险。

你可以通过以下语法创建一个元组:

复制代码
var result = (5, 20);

你也可以选择对元组中的值进行命名,这一点并不是必须的,只是让代码具有更好的可读性。

复制代码
var result = (count: 5, sum: 20);

你可能会想,“很棒的特性,但我自己也能写得出来”。但下一个特性才是重头戏。

多返回值

在类C 风格的语言中,要在一个函数中返回两个值始终是一件麻烦事。你只能选择将结果封装成某种结构,或是使用输出参数。与许多函数式编程语言一样,C#选择了第一种方式为你提供这一特性:

复制代码
(int, int) Tally (IEnumerable<int> list)

可以看到,在这里使用泛用的元组有一个基本问题:我们将无从得知每个字段的作用。因此,C#选择通过一个编译器花招对结果进行命名:

复制代码
(int Count, int Sum) Tally (IEnumerable<int> list)

我们在此需要强调一点:C#并没有生成一个新的匿名类型,你所获得的仍旧是一个元组,但编译器将假设它的属性为 Count 和 Sum,而不是 Item1 和 Item2。所以,以下代码行的作用都是等价的:

复制代码
var result = Tally(list);
Console.WriteLine(result.Item1);
Console.WriteLine(result.Count);

请注意一点,我们现在还不具备多赋值语法,如果这种语法最终实现,那么它的用法可能是这样的:

复制代码
(count, sum) = Tally(list);

除了提供简单的功能性函数之外,多返回值的实用性还体现在异步代码的编写上,因为在 async 函数中是不允许使用 out 参数的。

模式匹配:改进的 Switch 语法块

VB 与函数式程序员对于 C#抱怨得最多的一点就是 C#中的 switch 语句功能十分有限。VB 开发者希望能够进行范围匹配,而习惯了 F#或 Haskell 的开发者则希望能够使用分解式的模式匹配。C#打算同时提供这两种特性。

在对类型进行模式匹配时,你可以创建一个变量以保存转型的结果。举例来说,在对一个 System.Object 使用 switch 语句时,你可以编写以下代码:

复制代码
case int x:

如果该对象是数值类型,则变量 x 将得以赋值。否则的话,程序将按从上至下的顺序检查下一个 case 语句块。如果你想更具体地进行匹配,还可以使用范围检查:

复制代码
case int x when x > 0:
case int y:

在这个示例中,如果该对象是正整数,则 x 代码块将被执行。如果对象是 0 或负整数,而 y 代码块将被执行。

如果需要检查 null 值,则只需使用以下语法:

复制代码
case null;

模式匹配:分解

目前为止,我们仅仅展示了某种对 VB 中已有的特性所做的增量式改进,而模式匹配真正的强大之处在于分解,它可以将某个对象完全拆开,考虑一下以下语法:

复制代码
if (person is Professor {Subject is var s, FirstName is "Scott"})

这段代码完成了两件事:

  1. 它创建了一个本地变量 s,将其赋值为 ((Professor)person).Subject。
  2. 它执行了一次相等性检查 ((Professor)person).FirstName == “Scott”。

如果将其用 C# 6 代码改写则是这样:

复制代码
var temp = person as Professor;
if (temp != null && temp.FirstName == "Scott")
{
var s = temp.Subject

在最终发布中,我们预计能够同时看到对 switch 语句块的这两种改进。

引用返回

对于大数据结构进行引用传递比起值传递要快得多,因为后者需要对整个结构进行拷贝。与之类似,返回一个大数据结构的引用一样能够提升速度。

在类似于 C 这样的语言中,可以通过指针返回某个结构的引用。这种方式会带来一个常见的问题,即指针所指向的内存可能会因为某种原因而已经被回收了。

C#通过使用引用的方式回避这一问题,引用本身是一个附加了规则的指针。最重要的一条规则是,你不能够返回某个本地变量的引用。如果你尝试这样做,那么该变量所引用的栈信息在函数返回时就已经变得不可访问了。

在微软的展示代码中,它所返回的引用指向一个数组中的某个结构。由于它实质上是指向数组中某个元素的指针,因此随后可以对数组本身进行修改。举例来说:

复制代码
var x = ref FirstElement(myArray)
x = 5; //MyArray[0] now equals 5

这一语法的用例是对性能高度敏感的代码,在大多数应用中都无需使用这一特性。

二进制字面值(Binary Literals)

此次发布还引入了一个小特性,即二进制字面值。这一语法只是一个简单的前缀而已,例如 5 可以表示为“0b0101”。这一特性的主要用例是设置基于 flag 的枚举,以及创建位掩码(bitmask),以用于与 C 风格语言的互操作。

本地函数

本地函数是指在另一个函数中所定义的函数。第一眼看来,本地函数似乎只是比匿名函数稍好的一种语法。但它实际上还存在几个优点:

  • 首先,你无需为其分配一个委托以保存该函数。这不仅减少了内存压力,同时还允许编译器对该函数进行内联操作。
  • 其次,在创建闭包时,也无需为其分配一个对象,因为它能够直接访问本地变量。这一点同样能够改善性能,因为它也减少了 GC 的压力。

按照第二条规则推算,你将无法创建一个指向本地函数的委托。这一点对于代码的组织其实是一个优点,因为你无需创建独立的函数,并且将现有函数的状态作为显式的参数进行传递。

部分类的改进

最后演示的特性是一种处理部分类的新方式。在过去,部分类的应用是基于代码生成优先的概念而出现的。所生成的代码将包含一系列部分方法,开发者可以选择实现这些方法,以调整类的行为。

通过新的“replace”语法,开发者就多了一种新选择,能够以最直接的方式编写代码,随后再引入代码生成器,并重写这些方法。以下将通过一个简单的示例表现开发者的代码编写方式:

复制代码
public string FirstName {get; set;}

简单又清晰,但完全不符合 XAML 风格应用的写法。因此,代码生成器将生成如下代码:

复制代码
private string m_FirstName;
static readonly PropertyChangedEventArgs s_FirstName_EventArgs =new PropertyChangedEventArgs("FirstName")
replace public string FirstName {
get {
return m_FirstName;
}
set {
if (m_FirstName == value)
return;
m_FirstName = value;
PropertyChanged?.Invoke(this, m_FirstName_EventArg);
}

通过“replace”关键字,所生成的代码将直接替换手写的代码,添加所缺失的功能。在这个示例中,我们甚至还能够处理一些开发者经常会忽略的麻烦的部分,例如对 EventArgs 对象进行缓存。

虽然这个官方示例仅用于属性变更通知,但这一技术还可用于各种“面向切面编程(AOP)”的场景,例如在代码中注入日志记录、安全检查、参数校验以及其他各种繁琐的样板式代码。

如果读者想实际了解一下这些特性,可以观赏 Channel 9 中的视频“ The Future of C#”。

查看英文原文 C# 7 Features Previewed

【微软开发工具】 Visual Studio Community 提供了供个人开发者、开放源代码项目、学术研究、教育和小型专业团队的免费使用,并根据具体需求来创建面向 Windows、Android 和 iOS 的新式 App、WebApp 和云服务。

2016-04-06 19:005400
用户头像

发布了 428 篇内容, 共 180.6 次阅读, 收获喜欢 39 次。

关注

评论

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

打破软件开发“不可能三角” 只需一个低代码方案

力软低代码开发平台

联合解决方案|亚信科技AntDB携手蓝凌软件,助推企业数字化办公转型升级

亚信AntDB数据库

AntDB AntDB数据库 企业号 4 月 PK 榜

MobTech MobLink|无码邀请是怎么处理的

MobTech袤博科技

安全可信| 天翼云算力调度平台通过信通院首批可信算力云服务评估!

天翼云开发者社区

5月上海线下 · CSPO认证周末班【提前报名特惠】“价值交付课程”CST导师亲授

ShineScrum

软件测试/测试开发丨如何高效使用 Requests 做接口自动化测试

测试人

软件测试 自动化测试 接口测试 测试开发 requests

国营单位工作4年转行网络安全,成功上岸安全开发!

网络安全学海

黑客 网络安全 信息安全 渗透测试 WEB安全

GaussDB(DWS)云原生数仓技术解析

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 4 月 PK 榜

喜讯!天翼云荣获国际AI顶会ABAW季军

天翼云开发者社区

大咖说丨云计算:数字世界的“中枢神经”

天翼云开发者社区

5月上海线下 · CSM认证周末班【提前报名特惠】“全球金牌课程”CST导师亲授

ShineScrum

智改数转:这个制造业的必答题该如何作答?

加入高科技仿生人

低代码 数字化 制造业 智能化 智改数转

SketchUp Pro(草图大师2023)中文版 Mac/win

理理

SketchUp Pro 2023 SketchUp Pro中文版 草图大师2023下载

架构训练营模块二作业

请叫我馒头哥丶

架构实战营

5月在线 · A-CSM认证周末班【提前报名特惠】“敏捷教练必修课程”CST导师亲授

ShineScrum

基于SpringBoot实现单元测试的多种情境/方法(二)

天翼云开发者社区

重磅消息 | 2023年腾讯云从业者课程全面升级

科技热闻

社区分享 | Orillusion 引擎入门系列 —— 如何创建一个简单的 3D 示例

Orillusion

WebGL 元宇宙 web3d #WebGPU #开源

最新版本 Stable Diffusion 开源 AI 绘画工具之使用篇

极客飞兔

人工智能 图文生成 AI绘画 Stable Diffusion

如何通过Java代码将添加页码到PDF文档?

在下毛毛雨

Java PDF 添加页码

从“卖船”到提供建造“航母” 的基础设施,用友BIP有底气

用友BIP

保证高效写入查询的情况下,如何实现 CPU 资源和磁盘 IO 的最低开销?

TDengine

大数据 tdengine 数据处理 时序数据库 资源消耗

Ample Sound Ample Bass Upright III Mac(虚拟立式低音乐器)

理理

不动产行业国产化加速,明源云上榜《中国信创500强》

科技热闻

软件测试/测试开发丨两个步骤轻松搞定测试环境问题

测试人

软件测试 自动化测试 测试开发

算云融合促发展,天翼云以领先云网算力助推数字中国建设!

天翼云开发者社区

软件测试/测试开发丨通用 api 封装实战,带你深入理解 PO

测试人

软件测试 自动化测试 测试开发

Springfox与SpringDoc——swagger如何选择(SpringDoc入门)

天翼云开发者社区

分布式政企应用如何快速实现云原生的微服务架构改造

华为云开源

微服务 云原生

明道云技术路径选择及与LCDP的比较

明道云

C# 7特性预览_.NET_Jonathan Allen_InfoQ精选文章