百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

C# 8.0(c80混凝土一方多少钱)

bigegpt 2024-08-03 11:32 28 浏览

使用C#8.0中的模式,做得更多

Visual Studio 2019预览版2已经发布!伴随它的还有一些C#8.0的功能,供您试用。主要是关于模式匹配,但我会在最后提到一些其他的消息和变化。

更多地方的更多模式

当C#7.0引入模式匹配时,我们说我们希望将来在更多地方添加更多模式。是时候了!我们添加了我们称之为递归模式的内容,以及一种更紧凑的switch语句表达形式,称为Switch表达式您猜对了!)。

这是一个简单的C#7.0模式示例,让我们开始:

class Point{    public int X { get; }    public int Y { get; }    public Point(int x, int y) => (X, Y) = (x, y);    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);} static string Display(object o){    switch (o)    {        case Point p when p.X == 0 && p.Y == 0:            return "origin";        case Point p:            return #34;({p.X}, {p.Y})";        default:            return "unknown";    }}

Switch表达式

首先,让我们观察一下,许多switch语句在case内部并没有做太多有趣的工作。通常它们都只是生成一个值(如上所述),要么通过将值赋给变量,要么通过返回一个值。在所有这些情况下,switch语句坦率地说是笨重的。这感觉就像有着50年历史的语言特征,有太多的仪式感。

我们决定是时候添加switch表达式了。在这里,它应用于上述示例:

static string Display(object o){    return o switch    {        Point p when p.X == 0 && p.Y == 0 => "origin",        Point p                           => #34;({p.X}, {p.Y})",        _                                 => "unknown"    };}

这里有些做法与switch语句不同。让我们把它们列出来:

  • switch关键字是测试值和case 列表{...}之间的“中缀” 。这使得它更容易与其他表达式组合,并且更容易在视觉上区分switch语句。
  • 为简洁起见,case关键字和:被lambda箭头替换=>。
  • 为简洁起见,default被替换为 _ discard 模式。
  • 方法体就是表达式!所选方法体的结果,将成为switch表达式的结果。

由于表达式需要有一个值或抛出异常,因此到达末尾但没有匹配成功的switch表达式将引发异常。当出现这种可能的情况时,编译器会很好地警告你,但不会强迫你用一个catch-all来结束switch表达式:你知道则更好!

当然,现在由于我们的Display方法包含单个的return语句,我们可以将它简化为表达式体:

    static string Display(object o) => o switch    {        Point p when p.X == 0 && p.Y == 0 => "origin",        Point p                           => #34;({p.X}, {p.Y})",        _                                 => "unknown"    };

老实说,我不确定我们将在这里给出什么样的格式化指导,但应该清楚的是,这更加简洁和清晰的,特别是因为简洁性通常允许您以“表格”的方式格式化switch,如上所示,模式和方法体在同一行上,而=>排列成一列。

顺便说一句,我们计划在最后一个case之后允许一个尾随逗号,来与C#中所有其他的“大括号中的逗号分隔列表”保持一致,但预览2还不允许这样。

属性模式

说到简洁,模式突然变成了上面的switch表达式中最重要的元素!让我们做点什么。

请注意,switch表达式使用类型模式 Point p(两次),以及为第一个case添加附加条件的when子句。

在C#8.0中,我们向类型模式添加了更多的可选元素,这允许模式本身能够深入挖掘正在进行模式匹配的值。您可以通过添加包含嵌套模式的{...}使其成为属性模式, 来应用于值的可访问属性或字段。这让我们重写switch表达式如下:

static string Display(object o) => o switch{    Point { X: 0, Y: 0 }         p => "origin",    Point { X: var x, Y: var y } p => #34;({x}, {y})",    _                              => "unknown"};

两种情况仍然检查是否o是Point。然后,第一种情况将常量模式0递归地应用于p的X和Y属性,检查它们是否具有该值。因此,我们可以消除这个和许多常见情况中的when子句。

第二种情况将var模式应用于每个X和Y。回想一下,C#7.0 中的var模式总是成功的,它仅是声明一个新变量来保存该值。因此,x和y得到p.X和p.Y所包含的int值。

我们从不使用p,事实上可以省略它:

    Point { X: 0, Y: 0 }         => "origin",    Point { X: var x, Y: var y } => #34;({x}, {y})",    _                            => "unknown"

包括属性模式在内的所有类型模式,仍然存在的一点是,它们要求值为非null。这启发了“空”属性模式{}被用作紧凑的“非空”模式的可能性。例如,我们可以将最后一个case替换为以下两个case:

    {}                           => o.ToString(),    null                         => "null"

该{}处理剩下的非空对象,并null得到空值,所以switch是穷尽的,编译器不会抱怨有case没有考虑到。

位置模式

属性模式并没有使第二种Point情况更短,并且似乎不值得如此麻烦,但还是可以做更多事情来改变这一点。

请注意,Point该类有一个Deconstruct方法,即所谓的解构函数。在C#7.0中,解构器允许在赋值时解构一个值,这样您就可以编写例如:

(int x, int y) = GetPoint(); // split up the Point according to its deconstructor

C#7.0没有将解构与模式结合起来。在C#8.0中,这一点通过使用位置模式而发生了改变,位置模式是我们在C#8.0中对类型模式的进一步扩展。如果匹配类型是元组类型或具有解构函数,则可以使用位置模式作为应用递归模式的紧凑方式,而无需命名属性:

static string Display(object o) => o switch{    Point(0, 0)         => "origin",    Point(var x, var y) => #34;({x}, {y})",    _                   => "unknown"};

一旦对象被匹配为Point,解构函数就会被应用,嵌套模式也会被应用到结果值中。

解构函数并不总是合适的。只应将它们添加到这样的类型中:真正地清楚那些值是些什么值。例如Point,对于一个类,假设第一个值是X第二个值是Y,这是安全且直观的,因此上面的switch表达式直观且易于阅读。

元组模式

位置模式的一个非常有用的特殊情况是它们应用于元组时。如果将switch语句直接应用于元组表达式,我们甚至允许省略额外的括号集,例如switch (x, y, z)而不是switch ((x, y, z))。

元组模式非常适合同时测试输入的多个切片。这是一个状态机的简单实现:

static State ChangeState(State current, Transition transition, bool hasKey) =>    (current, transition) switch    {        (Opened, Close)              => Closed,        (Closed, Open)               => Opened,        (Closed, Lock)   when hasKey => Locked,        (Locked, Unlock) when hasKey => Closed,        _ => throw new InvalidOperationException(#34;Invalid transition")    };

当然,我们可以在switch-on的元组中,可选地包含hasKey而不是使用when子句 —— 这实际上是一个喜好问题:

static State ChangeState(State current, Transition transition, bool hasKey) =>    (current, transition, hasKey) switch    {        (Opened, Close,  _)    => Closed,        (Closed, Open,   _)    => Opened,        (Closed, Lock,   true) => Locked,        (Locked, Unlock, true) => Closed,        _ => throw new InvalidOperationException(#34;Invalid transition")    };

总而言之,我希望您能看到递归模式和switch表达式可以带来更清晰、更具声明性的程序逻辑。

预览2中的其他C#8.0功能

虽然这些模式功能是在VS 2019预览2中上线的主要功能,但有一些较小的功能,我希望您也会觉得它们既实用又有趣。我不会在这里详细介绍,只是简单介绍一下。

using声明

在C#中,using语句总是会导致嵌套级别,这可能非常烦人并且会损害可读性。对于您只想在一个范围结束时清理资源的简单情况,您现在有了using声明。using声明只是前面带有using关键字的局部变量声明,它们的资源在当前语句块的结尾处被释放。所以代替了:

static void Main(string[] args){    using (var options = Parse(args))    {        if (options["verbose"]) { WriteLine("Logging..."); }        ...    } // options disposed here}

你可以简单地写

static void Main(string[] args){    using var options = Parse(args);    if (options["verbose"]) { WriteLine("Logging..."); } } // options disposed here

Disposable ref structs

ref structs是在C#7.2中引入的,这里不是要重申其有用性,但反过来它们有一些严重的限制,例如无法实现接口。ref structs现在可以只需在其内有一个Dispose方法,即可在不实现IDisposable接口的情况变成Disposable

静态局部函数(Static local functions)

如果要确保local function不会产生与闭包作用域内“捕获”(引用)变量相关联的运行时成本,则可以将其声明为static。然后编译器将阻止引用闭包函数中声明的任何东西 —— 除了静态局部函数!

预览1后的更改

预览1的主要功能是可以为空的引用类型和异步流。在预览版2中,两者都有了一些改进,所以如果您已经开始使用它们,请注意以下几点。

可空的引用类型

我们添加了更多选项来控制源代码级别(通过#nullable和#pragma warning指令)和项目级别的可空警告。我们还将项目文件的选项更改为<NullableContextOptions>enable</NullableContextOptions>。

异步流

我们更改了编译器期望的IAsyncEnumerable<T>接口的形状!这使编译器与.NET Core 3.0 Preview 1中提供的接口不同步,这可能会给您带来一些麻烦。但是,.NET Core 3.0 Preview 2即将发布,这使接口恢复了同步。


下一篇 你们要的C#9

相关推荐

当Frida来“敲”门(frida是什么)

0x1渗透测试瓶颈目前,碰到越来越多的大客户都会将核心资产业务集中在统一的APP上,或者对自己比较重要的APP,如自己的主业务,办公APP进行加壳,流量加密,投入了很多精力在移动端的防护上。而现在挖...

服务端性能测试实战3-性能测试脚本开发

前言在前面的两篇文章中,我们分别介绍了性能测试的理论知识以及性能测试计划制定,本篇文章将重点介绍性能测试脚本开发。脚本开发将分为两个阶段:阶段一:了解各个接口的入参、出参,使用Python代码模拟前端...

Springboot整合Apache Ftpserver拓展功能及业务讲解(三)

今日分享每天分享技术实战干货,技术在于积累和收藏,希望可以帮助到您,同时也希望获得您的支持和关注。架构开源地址:https://gitee.com/msxyspringboot整合Ftpserver参...

Linux和Windows下:Python Crypto模块安装方式区别

一、Linux环境下:fromCrypto.SignatureimportPKCS1_v1_5如果导包报错:ImportError:Nomodulenamed'Crypt...

Python 3 加密简介(python des加密解密)

Python3的标准库中是没多少用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包:PyCrypto和cryptography上,我...

怎样从零开始编译一个魔兽世界开源服务端Windows

第二章:编译和安装我是艾西,上期我们讲述到编译一个魔兽世界开源服务端环境准备,那么今天跟大家聊聊怎么编译和安装我们直接进入正题(上一章没有看到的小伙伴可以点我主页查看)编译服务端:在D盘新建一个文件夹...

附1-Conda部署安装及基本使用(conda安装教程)

Windows环境安装安装介质下载下载地址:https://www.anaconda.com/products/individual安装Anaconda安装时,选择自定义安装,选择自定义安装路径:配置...

如何配置全世界最小的 MySQL 服务器

配置全世界最小的MySQL服务器——如何在一块IntelEdison为控制板上安装一个MySQL服务器。介绍在我最近的一篇博文中,物联网,消息以及MySQL,我展示了如果Partic...

如何使用Github Action来自动化编译PolarDB-PG数据库

随着PolarDB在国产数据库领域荣膺桂冠并持续获得广泛认可,越来越多的学生和技术爱好者开始关注并涉足这款由阿里巴巴集团倾力打造且性能卓越的关系型云原生数据库。有很多同学想要上手尝试,却卡在了编译数据...

面向NDK开发者的Android 7.0变更(ndk android.mk)

订阅Google官方微信公众号:谷歌开发者。与谷歌一起创造未来!受Android平台其他改进的影响,为了方便加载本机代码,AndroidM和N中的动态链接器对编写整洁且跨平台兼容的本机...

信创改造--人大金仓(Kingbase)数据库安装、备份恢复的问题纪要

问题一:在安装KingbaseES时,安装用户对于安装路径需有“读”、“写”、“执行”的权限。在Linux系统中,需要以非root用户执行安装程序,且该用户要有标准的home目录,您可...

OpenSSH 安全漏洞,修补操作一手掌握

1.漏洞概述近日,国家信息安全漏洞库(CNNVD)收到关于OpenSSH安全漏洞(CNNVD-202407-017、CVE-2024-6387)情况的报送。攻击者可以利用该漏洞在无需认证的情况下,通...

Linux:lsof命令详解(linux lsof命令详解)

介绍欢迎来到这篇博客。在这篇博客中,我们将学习Unix/Linux系统上的lsof命令行工具。命令行工具是您使用CLI(命令行界面)而不是GUI(图形用户界面)运行的程序或工具。lsoflsof代表&...

幻隐说固态第一期:固态硬盘接口类别

前排声明所有信息来源于网络收集,如有错误请评论区指出更正。废话不多说,目前固态硬盘接口按速度由慢到快分有这几类:SATA、mSATA、SATAExpress、PCI-E、m.2、u.2。下面我们来...

新品轰炸 影驰SSD多款产品登Computex

分享泡泡网SSD固态硬盘频道6月6日台北电脑展作为全球第二、亚洲最大的3C/IT产业链专业展,吸引了众多IT厂商和全球各地媒体的热烈关注,全球存储新势力—影驰,也积极参与其中,为广大玩家朋友带来了...