C#6.0 新增功能
C# 6.0 版本包含许多可提高开发人员工作效率的功能。 这些功能的总体效果是让你编写的代码更简洁、更具可读性。 该语法不像许多常见做法那样繁琐。 可以更轻松地看出设计意图。 好好了解这些功能可以帮助你提高生产力,编写更具可读性的代码。 你可以更专注于功能,而不是语言的构造。
本文的其余部分是对每个功能的概述,并提供用于探索每个功能的链接。 还可以在教程部分的 C# 6 交互式探索中探索这些功能。
public string FirstName { get; }
public string LastName { get; }
FirstName 和 LastName 属性只能在构造函数的主体中设置;
尝试在另一种普通方法中设置 LastName 会生成 CS0200 编译错误:

此功能实现用于创建不可变类型的真正语言支持且使用更简洁和方便的自动属性语法。
public class Student
{
public string FirstName { get; } = "张";
public string LastName { get; private set; } = "传宁";
}
FirstName,LaseName 成员在声明它的位置处被初始化。 这样,就能更容易地仅执行一次初始化。 初始化是属性声明的一部分,可更轻松地将存储分配。
ToString() 通常是理想之选:public override string ToString() => $"{LastName}, {FirstName}";
也可以将此语法用于只读属性:
public string FullName => $"{FirstName} {LastName}";
将现有成员更改为 expression bodied 成员是二进制兼容的更改。
using static System.Math;
Math 不包含任何实例方法。 还可以使用 using static 为具有静态和实例方法的类导入类的静态方法。 最有用的示例之一是 String:
using static System.String;
在 using static 语句中必须使用完全限定的类名 System.String。 而不能使用 string 关键字。
从 static using 语句导入时,仅在使用扩展方法调用语法调用扩展方法时,扩展方法才在范围内。 作为静态方法调用时,扩展方法不在范围内。 你在 LINQ 查询中会经常看到这种情况。 可以通过导入 Enumerable 或 Queryable 来导入 LINQ 模式。
using static System.Linq.Enumerable;
通常使用扩展方法调用表达式调用扩展方法。 在使用静态方法调用语法对其进行调用的罕见情况下,添加类名称可以解决歧义。
static using 指令还可以导入任何嵌套的类型。 可以引用任何嵌套的类型,而无需限定。
看下面的一个具体事例:
旧语法:
using System; namespace Demo002_NF46_CS60
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello world");
}
}
}
引入 using static 语法:
using static System.Console; namespace Demo002_NF46_CS60
{
class Program
{
static void Main(string[] args)
{
WriteLine("Hello world");
}
}
}
关于using static 的更具体的信息,请参考《using 静态指令》
. 替换为 ?.:var first = person?.FirstName;
在前面的示例中,如果 Person 对象是 null,则将变量 first 赋值为 null。 否则,将 FirstName 属性的值分配给该变量。 最重要的是?. 意味着当 person 变量为 null 时,此行代码不会生成 NullReferenceException。 它会短路并返回 null。 还可以将 null 条件运算符用于数组或索引器访问。 将索引表达式中的 [] 替换为 ?[]。

当 FirstName 为 null 时,变量 firstName 为 null,打印输出时不报错:

无论 person 的值是什么,以下表达式均返回 string。 通常,将此构造与“null 合并”运算符一起使用,以在其中一个属性为 null 时分配默认值。 表达式短路时,键入返回的 null值以匹配整个表达式。
first = person?.FirstName ?? "Unspecified";
还可以将 ?. 用于有条件地调用方法。 具有 null 条件运算符的成员函数的最常见用法是用于安全地调用可能为 null 的委托(或事件处理程序)。 通过使用 ?. 运算符调用该委托的 Invoke 方法来访问成员。 可以在委托模式一文中看到示例。
?. 运算符的规则确保运算符的左侧仅计算一次。 它支持许多语法,包括使用事件处理程序的以下示例:
// preferred in C# 6:
this.SomethingHappened?.Invoke(this, eventArgs);
确保左侧只计算一次,这使得你可以在 ?. 的左侧使用任何表达式(包括方法调用)。
public string FullName => $"{FirstName} {LastName}";
本示例使用替代表达式的属性。 可以使用任何表达式。 例如,可以在内插过程中计算学生的成绩平均值:
public string GetGradePointPercentage() => $"Name: {LastName}, {FirstName}. G.P.A: {Grades.Average():F2}";
上一行代码将 Grades.Average() 的值格式设置为具有两位小数的浮点数。
通常,可能需要使用特定区域性设置生成的字符串的格式。 请利用通过字符串内插生成的对象可以隐式转换为 System.FormattableString 这一事实。 FormattableString 实例包含组合格式字符串,以及在将其转换为字符串之前评估表达式的结果。 在设置字符串的格式时,可以使用 FormattableString.ToString(IFormatProvider) 方法指定区域性。 下面的示例使用德语 (de-DE) 区域性生成字符串。 (德语区域性默认使用“,”字符作为小数分隔符,使用“.”字符作为千位分隔符。)
FormattableString str = $"Average grade is {s.Grades.Average()}";
var gradeStr = str.ToString(new System.Globalization.CultureInfo("de-DE"));
true,则 catch 子句将对异常执行正常处理。 如果表达式计算结果为 false,则将跳过 catch 子句。 一种用途是检查有关异常的信息,以确定 catch 子句是否可以处理该异常:public static async Task<string> MakeRequest()
{
WebRequestHandler webRequestHandler = new WebRequestHandler();
webRequestHandler.AllowAutoRedirect = false;
using (HttpClient client = new HttpClient(webRequestHandler))
{
var stringTask = client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/about/");
try
{
var responseText = await stringTask;
return responseText;
}
catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
{
return "Site Moved";
}
}
}
相当于
catch (System.Net.Http.HttpRequestException e)
{
if(e.Message.Contains("")) // 如果判断的逻辑较多,建议使用该方式。
{
return "Site Moved";
}
}
nameof 表达式的计算结果为符号的名称。 每当需要变量、属性或成员字段的名称时,这是让工具正常运行的好办法。 nameof 的其中一个最常见的用途是提供引起异常的符号的名称:if (IsNullOrWhiteSpace(lastName))
{
throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
}
另一个用途是用于实现 INotifyPropertyChanged 接口的基于 XAML 的应用程序:
private string lastName;
public string LastName
{
get { return lastName; }
set
{
if (value != lastName)
{
lastName = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LastName)));
}
}
}
await 表达式的位置有若干限制。 使用 C# 6,现在可以在 catch 或 finally 表达式中使用 await。 这通常用于日志记录方案:public static async Task<string> MakeRequestAndLogFailures()
{
await logMethodEntrance();
var client = new System.Net.Http.HttpClient();
var streamTask = client.GetStringAsync("https://localHost:10000");
try
{
var responseText = await streamTask;
return responseText;
} catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains(""))
{
await logError("Recovered from redirect", e);
return "Site Moved";
}
finally
{
await logMethodExit();
client.Dispose();
}
}
在 catch 和 finally 子句中添加 await 支持的实现细节可确保该行为与同步代码的行为一致。 当在 catch 或 finally 子句中执行的代码引发异常时,执行将在下一个外层块中查找合适的 catch 子句。 如果存在当前异常,则该异常将丢失。 catch 和 finally 子句中的 awaited 表达式也会发生同样的情况:搜索合适的 catch,并且当前异常(如果有)将丢失。
鉴于此行为,建议仔细编写 catch 和 finally 子句,避免引入新的异常。
private Dictionary<int, string> messages = new Dictionary<int, string>
{
{ , "Page not Found"},
{ , "Page moved, but left a forwarding address."},
{ , "The web server can't come out to play today."}
};
可以将集合初始值设定项与 Dictionary<TKey,TValue> 集合和其他类型一起使用,在这种情况下,可访问的 Add 方法接受多个参数。 新语法支持使用索引分配到集合中:
private Dictionary<int, string> webErrors = new Dictionary<int, string>
{
[] = "Page not Found",
[] = "Page moved, but left a forwarding address.",
[] = "The web server can't come out to play today."
};
此功能意味着,可以使用与多个版本中已有的序列容器语法类似的语法初始化关联容器。
Add 方法使用扩展方法。 添加此功能的目的是进行 Visual Basic 的奇偶校验。 如果自定义集合类的方法具有通过语义方式添加新项的名称,则此功能非常有用。static Task DoThings()
{
return Task.FromResult();
}
在早期版本的 C# 中,使用方法组语法调用该方法将失败:
Task.Run(DoThings);
早期的编译器无法正确区分 Task.Run(Action) 和 Task.Run(Func<Task>())。 在早期版本中,需要使用 lambda 表达式作为参数:
Task.Run(() => DoThings());
C# 6 编译器正确地确定 Task.Run(Func<Task>()) 是更好的选择。
确定性的编译器选项
-deterministic 选项指示编译器为同一源文件的后续编译生成完全相同的输出程序集。
默认情况下,每个编译都生成唯一的输出内容。 编译器添加一个时间戳和一个随机生成的 GUID。 如果想按字节比较输出以确保各项生成之间的一致性,请使用此选项。
有关详细信息,请参阅 -deterministic 编译器选项文章。
C#6.0 新增功能的更多相关文章
- C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点
C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点 第一部分: C#是一种通用的,类型安全的,面向对象的编程语言.有如下特点: (1)面向对象:c# 是面向对象的范例的一个丰富实现, 它 ...
- C#2.0新增功能06 协变和逆变
连载目录 [已更新最新开发文章,点击查看详细] 在 C# 中,协变和逆变能够实现数组类型.委托类型和泛型类型参数的隐式引用转换. 协变保留分配兼容性,逆变则与之相反. 以下代码演示分配兼容性.协 ...
- C#基础拾遗系列之二:C#7.0新增功能点
第一部分: C#是一种通用的,类型安全的,面向对象的编程语言.有如下特点: (1)面向对象:c# 是面向对象的范例的一个丰富实现, 它包括封装.继承和多态性.C#面向对象的行为包括: 统一的类型系统 ...
- C#7.0新增功能点
原文地址: https://www.cnblogs.com/runningsmallguo/p/8972678.html 第二部分:C#7.0新增的功能 (1)数字字面量的提升: C#7中的数字文字 ...
- C#2.0新增功能01 分布类与分部方法
连载目录 [已更新最新开发文章,点击查看详细] 分部类型 拆分一个类.一个结构.一个接口或一个方法的定义到两个或更多的文件中, 每个源文件包含类型或方法定义的一部分,编译应用程序时将把所有部分组 ...
- 说说C# 8.0 新增功能Index和Range的^0是什么?
前言 在<C# 8.0 中使用 Index 和 Range>这篇中有人提出^0是什么意思?处于好奇就去试了,结果抛出异常.查看官方文档说^0索引与 sequence[sequence.Le ...
- Android 7.0 新增功能和api
Android 7.0 Nougat 为用户和开发者引入多种新功能.本文重点介绍面向开发者的新功能. 请务必查阅 Android 7.0 行为变更以了解平台变更可能影响您的应用的领域. 要详细了解 A ...
- Xcode 9.0 新增功能大全
Xcode是用于为Apple TV,Apple Watch,iPad,iPhone和Mac创建应用程序的完整开发人员工具集.Xcode开发环境采用tvOS SDK,watchOS SDK,iOS SD ...
- C#6.0新增功能
C# 6.0 版本包含许多可提高开发人员工作效率的功能. 此版本中的功能包括: 只读自动属性: 可以创建只能在构造函数中设置的只读自动属性. 自动属性初始值设定项: 可以编写初始化表达式来设置自动属性 ...
- C#8.0 新增功能
连载目录 [已更新最新开发文章,点击查看详细] C#8.0提供了许多增强功能 01 Readonly 成员 可将 readonly 修饰符应用于结构的任何成员. 它指示该成员不会修改状态. 这比 ...
随机推荐
- easyui在IE中: SCRIPT1003: 缺少 ':'
- Android无布局文件下自定义通知栏notification的 icon
在开发项目一个与通知栏有关的功能时,由于自己的项目是基于插件形式的所以无法引入系统可用的布局文件,这样无法自定义布局,造成无法自定义通知栏的icon. 在网上也有一种不用布局文件更换icon的方法,但 ...
- Z Order(Copy From WIN32.HLP)
The Z order of a window indicates the window's position in a stack of overlapping windows. This wind ...
- WebApp 安全风险与防护课堂(第二讲)开课了!
本文由葡萄城技术团队于原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 在昨天的公开课中,由于参与的小伙伴们积极性和热情非常高,我们的讲师Carl ...
- YARN分析系列之三 -- 从脚本入口分析 ResourceManager的初始化过程
1. 由脚本找到 RM 主类 这部分,我们从脚本作为入口去逐步深入ResourceManager源码. 从 Hadoop 官方文档 中可以看到 ResourceManager 的启动命令为: Usag ...
- net开发框架never
[一] 摘要 never是纯c#语言开发的一个框架,同时可在netcore下运行. 该框架github地址:https://github.com/shelldudu/never 同时,配合never_ ...
- 系统学习 Java IO (五)----使用 SequenceInputStream 组合多个流
目录:系统学习 Java IO---- 目录,概览 SequenceInputStream 可以将两个或多个其他 InputStream 合并为一个. 首先,SequenceInputStream 将 ...
- Spring Boot2从入门到实战:统一异常处理
都说管理的精髓就是“制度管人,流程管事”.而所谓流程,就是对一些日常工作环节.方式方法.次序等进行标准化.规范化.且不论精不精髓,在技术团队中,对一些通用场景,统一规范是必要的,只有步调一致,才能高效 ...
- wireshark数据包分析实战 第一章
1,数据包分析工具:tcpdump.wireshark.前者是命令行的,后者是图形界面的. 分析过程:收集数据.转换数据(二进制数据转换为可读形式).分析数据.tcpdump不提供分析数据,只将最原始 ...
- ubuntu镜像快速下载
由于官网服务器在国外,下载速度奇慢,所以我们可以利用阿里云镜像下载ubuntu ubuntu 14.04: http://mirrors.aliyun.com/ubuntu-releases/14.0 ...