下面是关于在C#7.0语言中计划功能的说明。其中大部分功能在Visual Studio “15” Preview 4中能运行。现在是最好的试用时期,请记录下你们的想法。

C#7.0语言增加了许多的新功能,促使专注于数据消费,简化代码和性能。

或许最大的特征是元组(tuples) ,使得它易于有多个结果,并从而简化代码是以对数据的形状为条件的模式匹配。但也有许多其他的一些功能希望将它们结合起来,让代码运行更高效,更明确,从而获得更多的创造性。如果有哪些运行不是你想要的或者有想改进的功能,在Visual Studio的窗口顶部使用“send feedback”功能将结果反馈给我们。在我所描述的许多功能在Preview 4还没有办法充分运行,根据用户的反馈结果,我们将在发布最终版是增加些新的功能。而必须要指出的是,现有计划中的一些功能在最终版也可能会有所改变或取消。

如果你对这个功能设置感兴趣并想学习它,在Roslyn GitHub site上可以找到许多的设计说明和相关讨论。

其它翻译版本(1)

输出(out)变量

目前在C#中,使用out参数并不像我们想象中那么流畅。在使用out参数调用方法时,你首先必须声明变量传递给它。虽然你通常不会初始化这些变量(他们将通过该方法后所有被覆盖),也不能使用VAR来声明他们,但是需要指定完整的类型:

public void PrintCoordinates(Point p)
{    int x, y; // have to "predeclare"p.GetCoordinates(out x, out y);WriteLine($"({x}, {y})");
}

在C#7.0,我们增加了Out变量,作为out参数传递的点来声明一个变量权:

public void PrintCoordinates(Point p)
{p.GetCoordinates(out int x, out int y);WriteLine($"({x}, {y})");
}

需要注意的是,变量是在封闭块范围内,所以后续可以使用它们。大多数类型的语句不建立自己的适用范围,因此out变量通常在声明中被引入到封闭范围。

其它翻译版本(1)

注:在Preview 4中,适用范围规则更为严格:out变量的作用域为它们在声明的说法。因此,上面的例子将会在下个版本中使用。

由于out变量直接声明作为参数传递给out参数,编译器通常可以告知类型(除非有冲突的过载)。所以这是很好用VAR,而不是一个类型来声明它们:

p.GetCoordinates(out var x, out var y);

out参数的一个常见的用途是Try...模式,其中out参数一个boolean return表示成功,out参数进行得到的结果:

public void PrintStars(string s)
{    if (int.TryParse(s, out var i)) { WriteLine(new string('*', i)); }    else {WriteLine("Cloudy - no stars tonight!"); }
}        

注:Preview 4处理的比较好的地方在于只是用if语句定义它。

计划允许“wildcards”作为out参数以及在*的形式,忽视不重要的out参数:

p.GetCoordinates(out int x, out *); // I only care about x

注:wildcards能否把它变成C#7.0还是个未知数。

其它翻译版本(1)

模式匹配

C# 7.0 引入了模式的概念,抽象地说,这是一种语法成分可以用来测试一个值是否有一个一定的“形”以及在它起作用时从值里面获取到的额外信息。

下面是 C# 7.0 中关于模式的例子:

  • c 的常量模式(c 是C#中的一个常量表达式),用于测试输入的参数是否和 c 相等

  • T x 的类型模式(T 是一个类型,x 是一个标识符),用于测试输入的参数是否有类型 T,如果有,提取输入参数的值到一个 T 类型的新 x 变量中。

  • var x 变量模式(x 是一个标识符),通常会匹配并简单地将输入参数的值放进一个新变量 x 中

这是个开始,模式是一种新的 C# 语言元素,而且我们将来可以把它们更多地增加到 C# 中。

其它翻译版本(1)

在 C# 7.0 中,我们正在使用模式以增强两种已存在的语言结构:

  • is 表达式现在在右边可以有一个模式,而不只是一个类型

  • case 子句在 switch 语句中现在可以通过模式匹配,而不仅仅是常量值

在将来的C#中,我们或许会增加更多能使用模式的地方。

带模式的 Is 表达式

这是一个使用带有常量模式和类型模式的 is 表达式的例子:

public void PrintStars(object o)
{    if (o is null) return;     // constant pattern "null"    if (!(o is int i)) return; // type pattern "int i"WriteLine(new string('*', i));
}

正如你所看到的,模式变量(变量通过模式引入)与先前描述的 out 变量有些类似,他们可以在表达式中被声明,而且可以在它们最近的周围范围内被使用。也像 out 变量那样,模式变量是易变的,

注: 就像 out 变量一样,严格的范围规则适用于 Preview 4.

模式和 Try 方法通常会一起出现:

if (o is int i || (o is string s && int.TryParse(s, out i)) { /* use i */ }

其它翻译版本(1)

带模式的 Switch 语句

我们正在泛化 switch 语句,因此:

  • 你可以在任何类型上使用 switch(不仅仅是原始类型)
  • 可以在 case 子句中使用模式
  • Case 子句可以拥有额外的条件

这里是一个简单的例子:

switch(shape)
{case Circle c:WriteLine($"circle with radius {c.Radius}");break;case Rectangle s when (s.Length == s.Height):WriteLine($"{s.Length} x {s.Height} square");break;case Rectangle r:WriteLine($"{r.Length} x {r.Height} rectangle");break;default:WriteLine("<unknown shape>");break;case null:throw new ArgumentNullException(nameof(shape));
}

有几件关于这个新扩展的 switch 语句的事需要注意:

  • case 子句的顺序现在很重要:就像 catch 子句,case 子句不再是必然不相交的,第一个子句匹配的将被选择。因此这里重要的是上面代码中 square case 比 rectangle case 来得要早。也是和 catch 子句一样,编译器会通过标记明显不能到达的情况来帮助你。在这之前,你永远无法知道评价的顺序,所以这不是一个重大改变的特性。
  • 默认子句总是最后被评价:即使上面代码中 null 子句是最后才来,它会在默认子句被选择前被检查。这是为了与现有 switch 语义相兼容。然而,好的做法通常会让你把默认子句放到最后。
  • null 子句在最后不可到达:这是因为类型模式遵循当前的 is 表达式的例子并且不会匹配空值。这保证了空值不会偶然被任何的类型模式捎来第一抢购。你必须更明确如何处理它们(或为默认子句留下他们)。

通过 case ...: 标签引入的模式变量仅存在于相对应的 switch 部分的范围内。

其它翻译版本(1)

元组

这是常见的希望从一个方法返回多个值的做法。目前可用的选项不是最佳的:

  • Out 参数。使用笨拙(即便有上面描述到的提升),它们不使用异步的方法运行。
  • System.Tuple<...>  返回类型。使用累赘并且需要一个元组对象的分配。
  • 为每个方法定制传输类型:大量的代码为了类型开销的目的仅是临时收集一些值
  • 匿名类型通过返回一个 dynamic 返回类型。高性能开销并且没有静态类型检查。

为了在这方面做得更好,C# 添加了tuple types 和 tuple literals:

(string, string, string) LookupName(long id) // tuple return type
{... // retrieve first, middle and last from data storagereturn (first, middle, last); // tuple literal
}

这个方法目前有效地返回三个字符串,将其作为元素在元组类型里包裹起来。

方法的调用者将会接受到一个元组,并且可以逐一访问元素。

var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");

Item1 等等,是元组元素的默认名字,并能够经常被使用。但它们不是太好描述的,因此你可以选择性地添加更好的一个。

(string first, string middle, string last) LookupName(long id) // tuple elements have names

现在元组的接受者拥有更多的可描述的名字用于运行:

var names = LookupName(id);
WriteLine($"found {names.first} {names.last}.");

你也可以在  tuple literals 中直接指定名字:

return (first: first, middle: middle, last: last); // named tuple elements in a literal

通常来说,你可以互相分配元组类型无关的名字,只要独立的元素是可以被分配的,元组类型会自如 转换成其他元组类型。特别是对于 tuple literals ,存在一些限制,这会警告或提示在常见的错误的情况下提示,例如偶然交换元素的名字。

注意:这些限制还没在 Preview 4 中实现

元组是值类型,而且他们的元素只是公开、易变的域。他们的值相等,代表这两个元组是相等的(都有相同的哈斯码)如果它们的元素都结对匹配(都有相同的哈斯码)。

这使得元组对于在多种返回值下的很多情况十分有用。举例来说,如果你需要一个有多种键的词典,使用元组作为你的键,然后一切东西就会如常工作。如果你需要在每个位置有一个有多种值的列表,使用元组,查找列表等等,程序会正常运行。

注意:元组依赖一系列底层类型,它们在 Preview 4 中不被引入。为了将来的工作,你可以通过 NuGget 轻易获取它们: 在 Solution Explorer 中右键点击项目,并选择“Manage NuGet Packages…” 选择“Browse”选项卡,检查“Include prerelease” 并且选择“nuget.org”作为“Package source” 搜索“System.ValueTuple”并安装它

解 构

另一种消除元组(tuple)的方法是解构元组。通过一个解构声明语法,把一个元组(或者其他的值)拆分为几部分,并且重新定义为新的变量。

(string first, string middle, string last) = LookupName(id1); // deconstructing decla
rationWriteLine($"found {first} {last}.");

在解构中可采用var关键字:

(var first, var middle, var last) = LookupName(id1); // var inside

或者把var关键字提取出来,在括号外:

var (first, middle, last) = LookupName(id1); // var outside

你也可以通过解构赋值来解构一个现有变量:

(first, middle, last) = LookupName(id2); // deconstructing assignment

不仅仅元组可以被解构,任何类型都可以被解构,只要有一个对应的(实体或者扩展)解构方法:

public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }

输出参数由解构之后的结果值构成。

(为什么采用数据参数代替返回一个元组?这样,你可以重载多个不同的数值)

class Point
{public int X { get; }public int Y { get; }public Point(int x, int y) { X = x; Y = y; }public void Deconstruct(out int x, out int y) { x = X; y = Y; }
}(var myX, var myY) = GetPoint(); // calls Deconstruct(out myX, out myY);

这将成为一种常见模式,包含析构函数和“对称”解析:

针对输出变量,我们计划在解构中允许使用“通配符”:

(var myX, *) = GetPoint(); // I only care about myX

注:仍然还没有确定是否将通配符引入C# 7.0中。

局部函数

有时,一个辅助函数只在一个使用它的单一方法内部有意义。现在你可以在其他功能体内部声明这些函数作为一个局部函数:

public int Fibonacci(int x)
{if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x));return Fib(x).current;(int current, int previous) Fib(int i){if (i == 0) return (1, 0);var (p, pp) = Fib(i - 1);return (p + pp, p);}
}

参数和闭合区间局部变量可用在局部函数内,类似lambda表达式。

举一个例子,方法实现迭代器通常需要严格检查调用时非迭代器封装方法。(迭代器本身没有运行,只到调用MoveNext 才会运行)。局部函数在这种情况下是完美的:

public IEnumerable<T> Filter<T>(IEnumerable<T> source, Func<T, bool> filter)
{if (source == null) throw new ArgumentNullException(nameof(source));if (filter == null) throw new ArgumentNullException(nameof(filter));return Iterator();IEnumerable<T> Iterator(){foreach (var element in source) {if (filter(element)) { yield return element; }}}
}

如果迭代器是一个私有方法的下一个过滤器,它将有可能被其他成员不小心使用(没有参数检查)。此外,作为过滤器,它将需要采取所有的相同的参数,而不是指定域内的参数。

注:在Preview 4版本中,本地函数必须在它们被调用之前声明。这个限制将被放松,能调用读取直接赋值的局部变量。

转载于:https://www.cnblogs.com/licin/p/6524508.html

C# 7.0特性与vs2017相关推荐

  1. Entity Framework Core 2.0 特性介绍和使用指南

    前言 这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升级EF也发展到EF6.x,Entity Framework Core是一个支持跨平台的全新版本, ...

  2. ASP.NET Core 2.0 特性介绍和使用指南

    ASP.NET Core 2.0 发布日期:2017年8月14日 ASP.NET团队宣布ASP.NET Core 2.0正式发布,发布Visual Studio 2017 15.3支持ASP.NET ...

  3. 1024 程序员节专题论坛来袭,权威解读 MindSpore、CANN 5.0 特性和 HCIA MDC 开发者认证...

    "授人以鱼不如授人以渔",一句古话中蕴含的发展真理,我们将其套用到如今炽手可热的 AI 领域之上会发现无比适用.2018 年,华为提出了普惠 AI 的概念,降低 AI 开发门槛,让 ...

  4. 实用知识点梳理:网络操作系统、HTTPS、交换机中用户权限、路由器与集线器功能、HTTP2.0特性

    网络操作系统 网络操作系统的基本任务: 屏蔽本地资源与网络资源之间的差异: 为用户提供基本的网络服务功能: 管理网络系统的共享资源: 提供网络系统的安全服务. HTTPS 在HTTP跟TCP中间多了一 ...

  5. .NET Core 2.0 特性介绍和使用指南

    前言 这一篇会比较长,介绍了.NET Core 2.0新特性.工具支持及系统生态,现状及未来计划,可以作为一门技术的概述来读,也可以作为学习路径.提纲来用. 对于.NET Core 2.0的发布介绍, ...

  6. .NET Standard 2.0 特性介绍和使用指南

    前言 早上起来.NET社区沸腾了,期待已久的.NET Core 2.0终于发布!根据个人经验,微软的产品一般在2.0时会趋于成熟,所以一个新的.Net开发时代已经来临!未来属于.NET Core. 对 ...

  7. RT-Thread 4.1.0 特性解析之LIBC与POSIX

    1. POSIX 渊源 可移植操作系统接口,POSIX 标准定义了操作系统(很多时候针对的是类 Unix 操作系统)应该为应用程序提供的接口标准,从而保证了应用程序在源码层次的可移植性,如今主流的 L ...

  8. Redis4.0、5.0、6.0、7.0特性整理(持续更新)

    最近研究研究新版本redis的新特性,网上查了查资料,这里记录一下. 0. Redis的版本迭代和里程碑 Redis从发布至今,已经有十余年的时光了,一直遵循着自己的命名规则: 版本号第二位如果是奇数 ...

  9. [转]细察 PHP V5.3.0 特性

    细察 PHP V5.3.0 特性 级别: 中级 Stephen B. Morris, CTO, Omey Communications 2009 年 12 月 07 日 随着流行的 PHP 语言的不断 ...

  10. OpenCL2.0特性之SVM

    from: http://blog.csdn.net/hdanbang/article/details/50198415 在OpenCL2.0中,增加了SVM(shared virtual memor ...

最新文章

  1. java工资高还是php_java和php哪个工资高
  2. 鼠标问题:鼠标拖拽不灵敏,准备复制拖动的半截就断了
  3. 股票历史数据下载接口踩坑记录
  4. 算法与数据结构(二)三元组矩阵行列式的计算(用递归)
  5. PHP拼接唯一索引,合并两个数组数据
  6. Atitit 提升记忆效率 有损压缩原理总结 目录 1. 常见方法 1 1.1. 抽象化提升一层 概念化 1 1.2. 骨架 ,目录化 大纲化 归纳整理 1 1.3. 提取关键词 ,摘要 ,
  7. 17.电话号码的字母组合(力扣leetcode) 博主可答疑该问题
  8. SQL 列转行和动态用时间生数据列
  9. svg 地图_用于Power BI的SVG省市地图(带数据标签,含下载)
  10. g的python实现_Python gevent协程切换实现详解
  11. tnl 的 masterServer, client server 架构学习笔记
  12. R语言使用dlnorm函数生成对数正态分布密度数据、使用plot函数可视化对数正态分布密度数据(logarithmic normal distribution)
  13. php懒人,关于php懒人函数的详细介绍
  14. tcp短连接TIME_WAIT问题解决方法大全(1)——高屋建瓴
  15. 移动端实现左右菜单联动效果(vue+better-scroll)
  16. 软件看板之父David Anderson:使用看板方法进行项目管理
  17. 量化交易学习系列13-系统交易的职业道路是什么
  18. 大型网站的架构设计图分享
  19. ros机器人编程实践(15.2)- 使用科大讯飞语音控制turtlebot导航
  20. 2023最新UI时光邮局系统+给未来写封信系统 PHP源码/美化版

热门文章

  1. 嵌入式系统调试仿真工具
  2. python中scrapy框架项目_Python -- Scrapy 框架简单介绍(Scrapy 安装及项目创建)
  3. JDK指定D盘安装及环境变量配置
  4. 给spring容器注册组件
  5. 内存管理之智能指针shared_ptr
  6. 这是来博客园的第二篇日志
  7. 新手填坑 java.lang.Integer cannot be cast to java.lang.String
  8. 《深入理解Android2》读书笔记(二)
  9. 使用IDEA,利用SpringMVC框架建立HelloWorld项目
  10. Dll学习心得(2)