展望C# 7

译者:雪落无痕 xdj

  目前的 C# 编译器(即 Roslyn)于 2014 年 4 月开源。目前不仅是编译器在 GitHub 上开发;语言的设计也是进行公开的讨论。 这允许感兴趣的各方了解语言下一个版本的样子。这篇文章概述了当前在设计语言新特性时的思考过程。如果你对现在 Roslyn 生态系统的更广泛的方面感兴趣的话,可以阅读 DotNetCurry(DNC)杂志 2016 年 3 月版上我的文章: .NET 编译器平台(Roslyn)概述 。

  下一版 C#的主题

  截止目前,每个版本的C#(C# 6.0 可能除外)都会围绕一个特定的主题:

  • C# 2.0 引入泛型。

  • C# 3.0 通过扩展方法、lambda 表达式、匿名类型和其他相关特性带来了 LINQ。

  • C# 4.0 都是关于与动态非强类型语言的互操作。

  • C# 5.0 简化异步编程和异步等待等关键词。

  • C# 6.0 完全重写,并且引入了各种各种更易实现的小特性和改进。你可以在 DotNetCurry(DNC)杂志 2016 年 1 月版上找到一篇C#6.0 特性的概述文章:U升级现有 C# 代码到 C# 6.0

  C# 7.0 可能不会有例外。语言设计者们目前专注于三个主题:

  • Web 服务的使用增长正在改变数据建模的方式。数据模型的定义正在成为服务契约的一部分,而不是在应用程序去完成。虽然这在函数式语言中是是非常方便的,但是它给面向对象开发带来了额外的复杂度。几个 C# 7 的特性正是以通过外部数据契约来简化该工作为目标的。

  • 日益增长的移动设备共享使得性能成为一个重要的考量因素。C# 7.0 的计划特性允许进行性能优化,以前这在 .Net 框架上是不可能的。

  • 可靠性和鲁棒性是软件开发中一个永恒的挑战。C# 7.0 可能用一部分开发时间来应对这个挑战。

  让我们仔细看看每个主题的一些计划中特性。

  处理数据

  面向对象语言比如 C# 在一组预定义的操作作用于一组可扩展的数据类型这样的场景中工作的很好。这些通常是通过一个接口(或者一个基类)对可用操作进行建模,以不断增加的子类表示数据类型。通过实现接口,类包含了各种操作的实现。

  比如,在一个游戏中,武器可能是各种不同类型(比如一把剑或者一张弓),并且操作可能也是不同的动作(比如攻击或者修复),增加一个新的武器类型(比如一把光剑)会很简单:创建一个新类,实现武器的接口。增加一个新动作(如转动)另外一方面就需要扩展接口和修改已有的武器实现。这在 C# 中是很自然的。


  在函数式编程中,数据类型不包括操作。相反,每一个函数对所有数据类型实现一个单一的操作。 这使得增加新操作(只需要定义一个新函数)更容易,但是增加新数据类型(需要修改所有已有相应的函数)却更难了。但是这在 C# 中是可能的了,它更加繁琐一些。


  模式匹配是可以帮助简化上述代码的特性。让我们来一步一步将它应用到 Attack 方法中:


  替代原有两句分离的语句来检查武器类型并将其赋值相应类型的变量,现在 is 操作符将允许我们声明一个新变量并分类类型值。

  类似的结果,一个 switch case 语句可以替代 if。这使得代码更加清晰,特别是有很多分支时:


  注意下 case 语句是如何同时做到类型转换和条件检查的,增加了代码的简洁性。

  另外一个模式匹配相关的特性是 switch 表达式。你可以认为它是一种 switch 语句,每个 case 分支都会返回一个值。使用这个特性,一个有限状态机的转换就可以定义在一个表达式中了。


  上面的代码还使用了另外一个特性: tuples。 它们被设计成更加轻量级的匿名类的替代品。他们主要被用在函数返回多个值时,替代 out 类型参数。

  更多函数式编程的开发方式会很快导致类只作为数据的容器,而不包含任何方法和业务逻辑。records 语法允许这种类的标准化实现,只需要最少的代码:

public class Sword (int Damage, int Durability);

  这简单的一行表示了一个完整的函数式类:

  正如你所看到的,这个类包含一些只读的属性,一个构造函数用来初始化这些属性。它还实现了 equality 方法,并使用基于 hash 的集合正确的重载了 GetHashCode, 比如 Dictionary 和 Hashtable。你可能不认识最后两个函数:

  • Is 操作符重载允许模式匹配时拆分成元组结构。

  • 为了解释 With 方法,请读下面几段。

  Record 将支持继承,但具体的语法还没定。

  增加可靠性

  上面使用 record 语法生成的 Sword 类,是不可变类的一个例子。这表示它的状态(属性的值)在类的实例创建后不能被改变。

  如果你想知道它跟可靠性有什么关系,想想多线程编程吧。随着处理器有更多核而不是更高时钟频率,在服务器、桌面和移动端,多线程编程只会变得更重要和更流行。同时不可变对象需要不同的编程方式,它在设计上就避免了多线程在没有合适的同步情况下修改同一对象时产生的条件竞争(比如,没有正确使用锁或者其他线程同步原语)。

  尽管现在 C# 中创建不可变对象也是可以的,但是它太复杂了。下面介绍的C#7.0 中的特性使得它更便捷的定义和使用不可变对象:

  · 对象初始化器只作用于只读属性,自动回落到匹配的构造函数上:

IWeapon sword = new Sword { Damage = 5, Durability = 500 };

  · 特殊的语法将用于创建简洁的对象副本:

IWeapon strongerSword = sword with { Damage = 8 };

  上面的表达式将创建一个 Sword 的副本对象,所有属性有相同的值,除了 Damage 使用新提供的值。完成这个表达式的内部运作的细节仍在讨论中。其中一个选项是需要的类有 With 方法,就像在 records 的例子中展示的那样:

public Sword With (int Damage = this.Damage, int Durability = this.Durability) => new Sword (Damage, Durability);

  这将使 with 表达式语法自动转换成下面的方法调用:

IWeapon strongerSword = sword.With (Damage: 8);

  C# 7 可靠性工作的第二部分是null 安全的主题。我们都同意 NullReferenceException 是最常见也最难以解决的失败之一。任何可以减少此类异常的数量的语言的改进肯定会对整个应用程序的可靠性有积极的影响。

  第三方供应商,如 JetBrains 著名 Visual Studio 扩展 ReSharper 已经在这个方向上走出了第一步。他们的工作是基于代码的静态分析,开发人员试图销毁一个对象之前没有检查 null 值时,发出警告。这是通过 Attibute 来实现的,可以用来标注方法是否可以返回 null 值。他们也为 BCL (基类库)类准备了标注。如果开发人员会正确地标注他/她所有的代码,静态分析应该能够可靠地警告任何潜在的 NullReferenceException 来源。

  C#语言设计团队正试图实现相同的目标,只不过是在语言层面上。核心思想是允许变量类型定义中包含是否可以赋值为空的信息:

IWeapon? canBeNull;
IWeapon cantBeNull;

  分配一个 null 值或潜在的 null 值给非空变量会导致编译器的警告(开发人员可以配置在这些警告的情况下构建失败,来增加额外的安全):

canBeNull = null;       // no warningcantBeNull = null;      // warningcantBeNull = canBeNull; // warning

  这种改变的问题是它破坏现有代码:它假设以前代码中所有变量都是非空的。为了应对这种情况,可以在项目级别禁用静态分析。开发人员可以决定何时进行 nullability 检查。

  在过去 C# 类似的改变已经被在考虑,但因为向后兼容性的问题没能实现。因为 Roslyn 已经改变了什么编译器和执行静态分析的诊断能力,语言团队决定再次重温这个话题。让我们保持祈祷,让他们设法想出一个可行的解决方案。

  改进的性能

  C# 7.0 中性能改进重点是减少内存位置中的数据复制。

  局部函数将允许在其他函数内部嵌套声明辅助函数。这不仅会缩小他们的作用域,也允许使用声明涵盖范围内的变量,而且不会在堆上分配额外的内存和堆栈:


  返回值和局部变量的引用也能用来阻止不必要的数据拷贝,同时他们的行为也改变了。因为这些变量指向原本的内存地址,任何对此处值的改变都会影响到局部变量的值:

  在上面的例子中,terrainType 是一个局部变量的引用,GetAt 是一个返回值的引用的函数:

public ref TerrainType GetAt (int x, int y) => ref terrain[x, y];

  Slices 是提出的最后的性能相关的特性:

var array = new int[] { 1, 2, 3, 4, 5 };var slice = Array.Slice (array, 0, 3); // refers to 1, 2, 3 in the above array

  Slice(切片) 使得将一个数组的一部分可以作为一个新的数组进行处理,而实际指向原数组的同一内存地址。

图1: Slices 是另一个数组的一部分

  同样的,对任何一个数组的修改将会同时影响两个数组,没有任何值被拷贝。这将导致较大状态的更有效的管理,比如在游戏中。所有需要的内存只需要在应用开始的时候分配一次,完全避免了新内存分配和垃圾收集。

  更进一步,它使我们可以用同样的方式获得一块原生的内存块,可以直接读取和写入,而不用再进行编组。

  尝试实验功能

  尽管所有上述的功能还远没有完成,任何工作已经可以在 GitHub 上使用。如果你有兴趣试试,你完全可以这样做。

  在撰写本文时,最简单的方式是安装 Visual Studio “15”预览版,从三月底起可以从此处下载。它包含新版的 C# 编译器,带有下列实验功能等着你来试用:模式匹配,局部函数返回值和局部变量的引用

  尚未成熟的特性需要你基于 GitHub 源码构建自己版本的编译器,这超出了本文讨论范围。如果你感兴趣,可以读下这篇详细指导的文章 。

  甚至在 Visual Studio “15”预览版中,默认情况下新的实验功能还是不能用的。

Image 2: Experimental features must be enabled explicitly

  尽管指示会有错误,在写代码时最简单的方式来启用这些功能的方法是在工程的编译属性里增加__DEMO__ 和 __DEMO_EXPERIMENTAL__条件编译符号。

  图3: 增加条件编译符号

  现在你就可以使用任何支持的实验语言特性了,编译工程也不会有错了。

  结论:

  所有本文描述的C# 7 新的语言功能都还在实现中。在C#7.0 的最终版本里,他们可能会很不一样或者根本不存在。这篇文章只是一个 C# 语言的当前状态的总览,让你能一窥未来,也许能引发你足够的兴趣去更紧密得跟踪开发,或者在新功能未完成时就去尝试下。通过在语言开发过程中作为一个更积极的部分,你就可以影响它,同时也能学到新东西;可能在下一版本可用之前就能改善你现有的编码实践。

原文地址:http://www.oschina.net/translate/csharp-7-new-expected-features


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 线程池详解及实例代码

转载自 Java 线程池详解及实例代码这篇文章主要介绍了Java 线程池的相关资料,并符实例代码,帮助大家学习参考,需要的朋友可以参考下线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资…

jQuery最简单的留言功能^-^

先上代码&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml" xml:lang"en"> <h…

rocketmq java home,rocketmq 安装与配置以及遇到的问题

不废话&#xff0c;搞起双M 模式环境1&#xff0c;java-1.8这里有个问题&#xff0c;centos 安装yum install java-1.8 是只是安装的java 运行环境jre&#xff0c;还缺少开发包所以在编译的时候会有问题&#xff0c;使用yum install yum install java-1.8.0-openjdk-devel* 这…

聊聊并发(八)——Fork/Join框架介绍

转载自 聊聊并发&#xff08;八&#xff09;——Fork/Join框架介绍1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架&#xff0c; 是一个把大任务分割成若干个小任务&#xff0c;最终汇总每个小任务结果后得到大任务结果的框架。 我们再通过F…

Mads Torgersen介绍C# 7及后续版本新特性

在QCon纽约2016大会上&#xff0c;C#项目经理Mads Torgersen介绍了即将到来的C# 7。他还简单地阐述了C#的演化过程&#xff0c;并展示了部分正在开发的未来版本特性。 近年来&#xff0c;云和分布式系统的出现使开发人员面临着新的挑战。开发人员需要进步&#xff0c;语言也要随…

Java的不同进制输出,[DanoR][Java小码][进制转换::将double转换为不同进制后用String输出]...

功能简述进制转换输入: 一个数(double),目标进制(int)和小数的保留位数(int)输出: 相应进制的表示方式(String)参数说明double number; //将要被转换的数int ary; //目标进制int accuracy; //指定小数保留的位数特性支持小数转换例0: (5.20, 8, 4) --> 5.146314631463146315…

小菜:Java异常处理的10个最佳实践

转载自 小菜&#xff1a;Java异常处理的10个最佳实践异常处理在编写健壮的 Java 应用中扮演着非常重要的角色。异常处理并不是功能性需求&#xff0c;它需要优雅地处理任何错误情况&#xff0c;比如资源不可用、非法的输入、null 输入等等。Java 提供很多异常处理特性&#x…

JavaScript的正则表达式实现邮箱校验

说到html5&#xff0c;在说邮箱校验&#xff0c;聪明的人已经想到了直接写个 电子邮箱&#xff1a;<input type"email" name"email">这样不就是自动校验邮箱了么。。。。 不错&#xff0c;这样也可以&#xff0c;但是我要说的是&#xff1a;在没有…

微软说它深爱着Linux,现在它用行动证明了

6.27 清晨&#xff0c;微软在Red Hat DevNation大会上正式发布了.NET Core以及ASP.NET Core 1.0&#xff0c;并提供了下载&#xff0c;其不仅能在Windows操作系统上运行&#xff0c;还能在Linux和Mac OS X操作系统上运行&#xff0c;这意味着开发者不仅能使用它来建立自己的应用…

php file_put_contents(quot;,php file_put_contents函数怎么用?

file_put_contents()是PHP中的是一个内置函数&#xff0c;用于将字符串写入文件。用户想要写入的文件的路径和必须写入的数据作为参数传递给函数&#xff0c;并返回成功时写入文件的字节数&#xff0c;失败时返回FALSE。php file_put_contents()函数怎么用&#xff1f;php file…

jdk1.8.0_45源码解读——ArrayList的实现

转载自 jdk1.8.0_45源码解读——ArrayList的实现 一、ArrayList概述 ArrayList是List接口的可变数组的实现。实现了所有可选列表操作&#xff0c;并允许包括 null 在内的所有元素。除了实现 List 接口外&#xff0c;此类还提供一些方法来操作内部用来存储列表的数组的大小。  …

.NET Core dotnet 命令大全

dotnet 命令大全&#xff0c;让你理解dotnet 命令。 本文将以一个实例串起 dotnet 所有命令&#xff0c;让你玩转dotnet 命令。 本篇文章编写环境为windows 10 &#xff0c;dotnet 命令同样适用于其它系统。 配合 VS Code 你就可以在 Linux 、MAC 上开发.NET Core。 下面是dotn…

java异常 字节码,Java字节码角度分析异常处理

目录从字节码角度来分析&#xff1a;异常处理1.1 异常-catch// 从字节码角度来分析&#xff1a;异常处理public class T13_ByteAnalyseException {public static void main(String[] args) {int i 0;try {i 10;} catch (Exception e) {i 20;}}}注意&#xff1a;为了抓住重点…

html特效大全1

提前声明&#xff1a;好久之前的文档&#xff0c;找不着出处&#xff0c;如有侵权&#xff0c;联系本人&#xff0c;马上处理&#xff01; 1) 贴图&#xff1a;<imgsrc"图片地址"> 2)加入连接&#xff1a;<a href"所要连接的相关地址">写上你…

.Net Core 系列:1、环境搭建

前言&#xff1a; 2016年6月28日微软宣布发布 .NET Core 1.0、ASP.NET Core 1.0 和 Entity Framework Core 1.0。 .NET Core是微软在两年前发起的开源跨平台.NET框架项目&#xff0c;支持Windows、OS X和Linux平台&#xff0c;可用于开发各种类型的应用。此次发布包括了 .NET C…

【集合框架】JDK1.8源码分析之HashMap(一)

转载自 【集合框架】JDK1.8源码分析之HashMap&#xff08;一&#xff09;一、前言在分析jdk1.8后的HashMap源码时&#xff0c;发现网上好多分析都是基于之前的jdk&#xff0c;而Java8的HashMap对之前做了较大的优化&#xff0c;其中最重要的一个优化就是桶中的元素不再唯一按照…

java 连接 sql2005,java与sql server2005 连接有关问题

当前位置:我的异常网 Eclipse java与sql server2005 连接有关问题java与sql server2005 连接有关问题www.myexceptions.net 网友分享于&#xff1a;2013-01-27 浏览&#xff1a;73次java与sql server2005 连接问题package com.lzw.dao;import internalFrame.guanli.Item;imp…

微软借Bletchley项目将云计算信息加入区块链

在比特币领域大获成功后&#xff0c;越来越多的行业开始尝试通过区块链&#xff08;Blockchain&#xff09;技术在自己的业务中实施分布式分类帐&#xff08;Ledger&#xff09;。 InfoQ 什么是区块链 区块链是一种用于创建数字交易分类帐的数据结构&#xff0c;或有关某笔交易…

php定时某个时间循环做,PHP定时循环执行脚本

代码如下&#xff1a;<?php ignore_user_abort(); //关掉浏览器&#xff0c;PHP脚本也可以继续执行.set_time_limit(0); // 通过set_time_limit(0)可以让程序无限制的执行下去$interval 43200; // 每隔*秒运行&#xff0c;这里是12小时执行一次$is_send true;//是否开启t…

LinkedList 的实现原理浅析

转载自 LinkedList 的实现原理浅析 LinkedList内部结构 查看LinkedList的源码&#xff0c;发现其继承自AbstractSequentialList&#xff0c;实现了List&#xff0c;Deque&#xff0c;Cloneable以及Serializable接口&#xff0c;如&#xff1a; 也就意味着&#xff1a; Linked…