Take C# 8.0 for a spin

本文章为机器翻译。https://blogs.msdn.microsoft.com/dotnet/2018/12/05/take-c-8-0-for-a-spin/

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/ 访问。

以C # 8兜风
我们昨天宣布Visual Studio 2019的第一个预览(让每个开发人员在Visual Studio 2019更高效)和3(网络核心。宣布.NET核心3预览版1和开源的Windows桌面框架)。

一个令人兴奋的方面是,你可以玩一些功能来# 8 C!在这里,我要带你一个小导游通过三个新的C #功能,你可以尝试在预览。不是所有# 8特点是可用的。如果你想对所有主要功能的概述,请阅读文章# C栋8,或查看短(13分钟)的视频“什么是新的C # 8”9频道或YouTube。

准备
首先,下载并安装预览1网芯3。和Visual Studio 2019 1预览。在Visual Studio中,确保你选择的工作量”。网核心的跨平台开发”(如果你忘了,你可以把它添加后打开Visual Studio安装程序,单击“Visual Studio 2019版修改”)。

启动Visual Studio 2019预览,创建一个新的项目,并选择“控制台应用程序(.NET核心)”的项目类型。

一旦项目启动和运行,改变它的目标框架,.NET核心3(右键单击解决方案资源管理器中,项目选择属性,使用下拉菜单上的“应用程序”选项卡)。Then select C# 8.0 as the language version (on the Build tab of the project page click “Advanced…” and select “C# 8.0 (beta)”).

Now you have all the language features and the supporting framework types ready at your fingertips!

Nullable reference types
The nullable reference types feature intends to warn you about null-unsafe behavior in the code. Since we didn’t do that before, it would be a breaking change to just start now! To avoid that, you need to opt in to the feature.

Before we do turn it on, though, let’s write some really bad code:

using static System.Console;

class Program
{
static void Main(string[] args)
{
string s = null;
WriteLine($“The first letter of {s} is {s[0]}”);
}
}
If you run it you get, of course, a null reference exception. You’ve fallen into the black hole! How were you supposed to know not to dereferencesin that particular place? Well duh, because null was assigned to it on the previous line. But in real life, it’s not on the previous line, but in somebody else’s assembly running on the other side of the planet three years after you wrote your line of code.How could you have known not to write that?That’s the question that nullable reference types set out to answer! So let’s turn them on!

For a new project you should just turn them on right away. In fact I think they should probably be on by default in new projects, but we didn’t do that in the preview. The way to turn them on is to add the following line to your .csproj file, e.g. right after the LanguageVersion that was just inserted when you switched to C# 8.0 above:

true
Save the .csproj file and return to your program: What happened? You got two warnings! Each represents one “half” of the feature. Let’s look at them in turn. The first one is on the无效的in this line:

string s = null;
它抱怨你把null赋值给“非可空类型”:whaaat?!?当该功能开启空常引用类型不再受欢迎如字符串!因为,你知道的,零不是一个字符串!我们假装了面向对象编程的最后五十年,但实际上零其实不是一个对象:这就是为什么所有的爆炸,当你想把它像一个!

所以没有更多的是:空是禁止的,除非你问了。怎么做你问了吗?通过使用可空类型的引用,如字符串。后面的问号,允许信号无效:

字符串S = null;
警告消失:我们已经明确表示,这个变量保存空的意图,所以现在很好。

直到下一行代码!就行了

WriteLine($”的第一个字母,{ }是{ } [ 0 ]”);
它抱怨S进入s[0]that you may be dereferencing a null reference. And sure enough: you are! Well done, compiler! How do you fix it, though? Well that’s pretty much up to you – whichever way you would always have fixed it! Let’s try for starters to only execute the line whensis not null:

if (s != null) WriteLine($“The first letter of {s} is {s[0]}”);
The warning goes away! 为什么?Because the compiler can see that you only go to the offending code whens是不无效的.It actually does a full flow analysis, tracking every variable across every line of code to keep tabs on where it might be null and where it probably won’t be. It watches your tests and assignments, and does the bookkeeping.

Let’s try another version:

WriteLine($“The first letter of {s} is {s?[0] ?? ‘?’}”);
This uses the null conditional indexing operators?[0]which avoids the dereference and produces a null ifsis null. Now we have a nullablechar?, but the null-coalescing operator?? '?'replaces a null value with the烧焦 ‘?’。So all null dereferences are avoided. The compiler is happy, and no warnings are given.

As you can see, the feature keeps you honest while you code: it forces you to express your intent whenever you want null in the system, by using a nullable reference type. And once null is there, it forces you to deal with it responsibly, making you check whenever there’s a risk that a null value may be dereferenced to trigger a null reference exception.

Are you completely null-safe now? No. There are a couple of ways in which a null may slip through and cause a null reference exception:

If you call code that didn’t have the nullable reference types feature on (maybe it was compiled before the feature even existed), then we cannot know what the intent of that code was: it doesn’t distinguish between nullable and nonnullable – we say that it is “null-oblivious”. So we give it a pass; we simply don’t warn on such calls.
The analysis itself has certain holes. Most of them are a trade-off between safety and convenience; if we complained, it would be really hard to fix. For instance, when you writenew string[10], we create an array full of nulls, typed as non-null字符串s. We don’t warn on that, because how would the compiler keep track of you initializing all the array elements?
But on the whole, if you use the feature extensively (i.e. turn it on everywhere) it should take care of the vast majority of null dereferences.

It is definitely our intention that you should start using the feature on existing code! Once you turn it on, you may get a lot of warnings. Some of these actually represent a problem: Yay, you found a bug! Some of them are maybe a bit annoying; your code is clearly null safe, you just didn’t have the tools to express your intent when you wrote it: you didn’t have nullable reference types! For instance, the line we started out with:

string s = null;
That’s going to be super common in existing code!And as you saw, we did get a warning on the next line, too, where we tried to dereference it.So the assignment warning here is strictly speaking superfluous from a safety standpoint: It keeps you honest in new code, but fixing all occurences in existing code would not make it any safer.For that kind of situation we are working on a mode where certain warnings are turned off, when it doesn’t impact the null safety, so that it is less daunting to upgrade existing code.

Another feature to help upgrade is that you can turn the feature on or off “locally” in your code, using compiler directives#nullable enable和#nullable disable。That way you can go through your project and deal with annotations and warnings gradually, piece by piece.

To learn more about nullable reference types check out theOverview of Nullable typesand theIntroduction to nullable tutorial打开(放)docs.microsoft.com。

For a deeper design rationale, last year I wrote a postIntroducing Nullable Reference Types in C#。

If you want to immerse yourself in the day-to-day of the design work, look at theLanguage Design Noteson GitHub, or follow along as I try to put together aNullable Reference Types Specification。

范围和指标
C #越来越表现在索引数据结构。想要简单的语法切出数组的一部分,字符串或跨越?现在你可以!

去改变你的程序如下:

使用系统。收藏。通用;

使用静态系统控制台;

类节目

{

static void main(String [] args
{)

foreach(变量名在getnames())

{

WriteLine(名称);

}

}

静态IEnumerable <字符串> getnames()

{

字符串[]名字=

{

“阿基米德”、“毕达哥拉斯”、“Euclid”、“Socrates”、“Plato”

};

foreach(变量名的名字)
我们去的那点代码遍历数组的名字。修改foreach如下:

foreach(名字[ 1 … 4 ]变量名)
它看起来像我们遍历1到4名。的确,当你运行它的时候,会发生什么事情!端点独家4元,即不包括。1的4。实际上是一个范围的表达,并没有发生像在这里,作为一个索引操作部分。它有一种自己的,称为范围。只要我们想,我们可以把它变成自己的变量,它会一样工作:

范围为1。4;

foreach(var名称名称[范围
一系列表达的端点不必处理。事实上,他们是一个类型,指数非负整数转换。但你也可以创建一个指数一个新的运营商,意为“结束”。所以 1是一个从端:

foreach(名字[ 1 … ^ 1 ])变量名
本机型在阵列的每个端元,产生一个与中三个元素的数组。

范围表达式或两端开放。^ 1 …是一样的0、^ 1。1 …是一样的1、^ 0。和…是一样的0、^ 0:开始到结束。所有这些尝试看看!尝试混合和匹配“开始”和“结束”指数ES的两端范围看看会发生什么。

范围不仅仅是用来使用的索引。例如,我们计划要重载string.substring,跨。片和asspan扩展方法,以范围。那些不在这个预览网芯3虽然。

异步数据流
IEnumerable 在C #特殊作用。”ienumerables”代表各种不同的数据序列,而语言有消费和生产的特殊结构。

在我们目前的计划看,他们被通过foreach声明,这是获得一个枚举数的苦工,反复推进,提取沿途的元素,最后将枚举器。他们可以制作迭代器方法::生利他们被要求通过消费元素。都是同步的,但结果更好的准备的时候,他们的要求,或线程块!

异步和等待添加到C #处理结果,不一定要准备好当你问他们。他们可以异步等待ED,和线程可以去做其他的东西,直到他们成为可用。但这只对单一的价值观,没有序列,逐步和异步产生的时间,如从一个物联网传感器或数据流从一个服务实例的测量。

异步数据流,使异步和枚举接口在C #!让我们来看看,通过逐步“async’ifying“我们目前的计划。

首先,让我们添加另一个使用在文件的顶部指令:

使用system.threading.tasks;
现在让我们来模拟getnames做一些异步工作加在名字异步延迟生利预计起飞时间:

等待任务。延迟(1000);

产量;
当然,我们得到一个错误,你只能等待在一个异步方法所以让我们异步:

静态异步IEnumerable <字符串> getnames()
现在我们说,我们不能返回正确的类型为一个异步方法,这是公平的。但在类型列表的新候选人可以除了通常的回报任务东西IAsyncEnumerable。This is our async version ofIEnumerable!Let’s return that:

static async IAsyncEnumerable GetNames()
Just like that we’ve produced an asynchronous stream of strings! In accordance with naming guidelines, let’s renameGetNames到GetNamesAsync。

static async IAsyncEnumerable GetNamesAsync()
Now we get an error on this line in the主要方法

foreach (var name in GetNamesAsync())
Which doesn’t know how to foreach over anIAsyncEnumerable。That’s because foreach’ing over asynchronous streams requires explicit use of the等待关键词

await foreach (var name in GetNamesAsync())
It’s the version of foreach that takes an async stream and awaits every element! Of course it can only do that in an async method, so we have to make our主要method async. 幸运的是,C # 7.2增加支持:

静态异步任务主要(string [] args)
现在所有的线条都消失了,和程序的正确性。但如果你编译并运行它,你会得到一个尴尬的错误数。那是因为我们搞砸了一点,并没有得到预览。网芯3和Visual Studio 2019完全一致。具体来说,有一种类型的迭代器实现异步杠杆的不同,什么编译器期望。

您可以通过添加一个单独的源文件到你的项目中解决这个问题,含这桥码。重新编译,一切都应该是不错的。

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/ 访问。

接下来的步骤
请让我们知道你在想什么!如果你尝试这些功能,如何提高他们的想法,请使用反馈按钮在Visual Studio 2019预览。整个目的预览是有一个最后的机会,当然是正确的,基于怎样的特点发挥出在手生活的真实用户,所以请让我们知道!

快乐的黑客,

MADS托格森,C #设计领先

猜你喜欢

转载自blog.csdn.net/qq_31116753/article/details/85314299
今日推荐