【译】C#9的候选功能

640?wx_fmt=gif

通往C# 9 的漫长道路已经开始了,这是世界上第一篇关于C# 9候选功能的文章。阅读完本文后,你将希望为将来遇到新的C#挑战做好充分准备。 这篇文章基于:

  • C#语言版本计划 9.0 候选功能

基于记录和模式匹配的表达式

我一直在长时间等待这个功能。记录是一种轻量级的不可变类型。它们是名义上的类型,可能有(方法、属性、运算符等),并允许你比较结构相等。此外,在默认情况下,记录属性是只读的。

记录可以是值类型或者引用类型。

例如:

public class Point3D(double X, double Y, double Z);    	
public class Demo     	
{    	public void CreatePoint()    	{    	var p = new Point3D(1.0, 1.0, 1.0);  	}  	
}  

上面的代码转换为:

  1. public class Point3D

  2. {

  3. private readonly double <X>k__BackingField;

  4. private readonly double <Y>k__BackingField;

  5. private readonly double <Z>k__BackingField;

  6. public double X {get {return <X>k__BackingField;}}

  7. public double Y{get{return <Y>k__BackingField;}}

  8. public double Z{get{return <Z>k__BackingField;}}


  9. public Point3D(double X, double Y, double Z)

  10. {

  11. <X>k__BackingField = X;

  12. <Y>k__BackingField = Y;

  13. <Z>k__BackingField = Z;

  14. }


  15. public bool Equals(Point3D value)

  16. {

  17. return X == value.X && Y == value.Y && Z == value.Z;

  18. }


  19. public override bool Equals(object value)

  20. {

  21. Point3D value2;

  22. return (value2 = (value as Point3D)) != null && Equals(value2);

  23. }


  24. public override int GetHashCode()

  25. {

  26. return ((1717635750 * -1521134295 + EqualityComparer<double>.Default.GetHashCode(X)) * -1521134295 + EqualityComparer<double>.Default.GetHashCode(Y)) * -1521134295 + EqualityComparer<double>.Default.GetHashCode(Z);

  27. }

  28. }


  29. Using Records:


  30. public class Demo

  31. {

  32. public void CreatePoint()

  33. {

  34. Point3D point3D = new Point3D(1.0, 1.0, 1.0);

  35. }

  36. }

新建议的特性“带表达式”的记录建议,你可以像下面这样使用: varnewPoint3D=point3D.With(x:42);创建一个新的点(newPoint3D)就像一个已存在的点(point3D),但是X的值变为了42。

这种特性在模式匹配方面非常有效。我将在另一篇文章中介绍这个主题。

F#中记录

从MSDN中的例子复制的F#代码,类型 Point3D={X:float; Y:float; Z:float}

  1. let evaluatePoint (point: Point3D) =

  2. match point with

  3. | { X = 0.0; Y = 0.0; Z = 0.0 } -> printfn "Point is at the origin."

  4. | { X = xVal; Y = 0.0; Z = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal

  5. | { X = 0.0; Y = yVal; Z = 0.0 } -> printfn "Point is on the y-axis. Value is %f." yVal

  6. | { X = 0.0; Y = 0.0; Z = zVal } -> printfn "Point is on the z-axis. Value is %f." zVal

  7. | { X = xVal; Y = yVal; Z = zVal } -> printfn "Point is at (%f, %f, %f)." xVal yVal zVal


  8. evaluatePoint { X = 0.0; Y = 0.0; Z = 0.0 }

  9. evaluatePoint { X = 100.0; Y = 0.0; Z = 0.0 }

  10. evaluatePoint { X = 10.0; Y = 0.0; Z = -1.0 }

这段代码的输出如下:

  • Point is at the origin.

  • Point is on the x-axis. Value is 100.000000.

  • Point is at(10.000000, 0.000000, -1.000000).

我想到的第一个问题是为什么我们需要记录?使用结构不是更好吗?

为回答这个问题,我从Reddit发表一个引用:

结构是需要一些准则来实现。你不必使他们不可变。不必实现值相等逻辑。不必使他们具有可比性。如果不这样做,你将失去所有的便利,但是编译器不会强制任何的这些约束

记录类型由编译器实现,这意味着你必须满足所有的条件并且不能出现错误。

因此,他们不仅可以节省大量的样板,还可以消除一大堆潜在bugs。

此外,这个功能在F#中已存在十多年,其他语言如(Scala,Kotlin)也有类似概念。

支持构造函数和记录的其他语言示例:F# 

typeGreeter(name:string)=memberthis.SayHi()=printfn"Hi, %s"name

Scala

  1. class Greeter(name: String)

  2. {

  3. def SayHi() = println("Hi, " + name)

  4. }

Kotlin

  1. class Greeter(val name: String)

  2. {

  3. fun sayhi()

  4. {

  5. println("Hi, ${name}");

  6. }

  7. }

同时,我们使用C#要编写这么长的代码,

  1. public class Greeter

  2. {

  3. private readonly string _name;

  4. public Greeter(string name)

  5. {

  6. _name = name;

  7. }

  8. public void Greet()

  9. {

  10. Console.WriteLine($ "Hello, {_name}");

  11. }

  12. }

当这个功能完成后,我们可以将C#代码减少到,

  1. public class Greeter(name: string)

  2. {

  3. public void Greet()

  4. {

  5. Console.WriteLine($ "Hello, {_name}");

  6. }

  7. }

更少的代码!我喜欢它!

类型类(Type Classes)

此特性的灵感来自Haskell,她是我喜欢的功能。正如我之前在两年前我的文章中所说,C#将实现更多函数式编程概念,这就是FP概念之一。在函数式编程中,类型类允许你在类型上添加一组操作,但是不能实现它。由于实现是在其他地方完成的,这是一种多态,但是比面向对象编程语言中的经典类更灵活或ad-hoc。

类型类和C#中的接口具有相似的用途,但是它们的工作方式有所不同,在某些情况下,类型类更多的是直接使用,因为它是直接在固定类中工作,而不是继承层次结构的片段中。

此功能最初与“扩展所有内容”特性一起被引入,可以将它们组合在一起,如下面Mads Torgersen示例中所示。

我引用了官方提案中的一些文字:

一般来说,“形状”声明非常类似于接口声明,除了它

  • 几乎可以定义任何类型的长远(包括静态成员)

  • 可以通过扩展实现

  • 只能在某些地方用作类型

Haskell 类型类例子:

  1. class Eq a where

  2. (==) :: a -> a -> Bool

  3. (/=) :: a -> a -> Bool

"Eq"为类名,而==,/=是类中的操作,类型“a”是类型“Eq”的实例

Haskell示例作为通用C#接口,

  1. interface Eq <A>

  2. {

  3. bool Equal(A a, A b);

  4. bool NotEqual(A a, A b);

  5. }

Haskell示例作为C# 9 中的类型类(shape是类型类中一个新的独特关键字)

  1. shape Eq<A>

  2. {

  3. bool Equal(A a, A b);

  4. bool NotEqual(A a, A b);

  5. }

示例显示接口和类型类直接的语法相似

  1. interface Num<A>

  2. {

  3. A Add(A a, A b);

  4. A Mult(A a, A b);

  5. A Neg(A a);

  6. }


  7. struct NumInt : Num<int>

  8. {

  9. public int Add(int a, int b) => a + b;

  10. public int Mult(int a, int b) => a * b;

  11. public int Neg(int a) => -a;

  12. }

使用C# 9 类型类

  1. shape Num<A>

  2. {

  3. A Add(A a, A b);

  4. A Mult(A a, A b);

  5. A Neg(A a);

  6. }


  7. instance NumInt : Num<int>

  8. {

  9. int Add(int a, int b) => a + b;

  10. int Mult(int a, int b) => a * b;

  11. int Neg(int a) => -a;

  12. }

Mads Torgersen 示例

重要信息:shape不是一个类型。相反,shape主要目的是用作通用约束,显示类型参数以具有一个正确的shape。同时允许声明的主体可以使用shape。

原始代码

  1. public shape SGroup<T>

  2. {

  3. static T operator +(T t1, T t2);

  4. static T Zero {get;}

  5. }

这个声明说如果类型在T上实现了一个+运算符,那么它可以是SGroup,并且是一个零静态属性。

  1. public extension IntGroup of int: SGroup<int>

  2. {

  3. public static int Zero => 0;

  4. }

添加一个扩展:

  1. public static AddAll<T>(T[] ts) where T: SGroup<T> // shape used as constraint

  2. {

  3. var result = T.Zero; // Making use of the shape's Zero property

  4. foreach (var t in ts) { result += t; } // Making use of the shape's + operator

  5. return result;

  6. }

让我们使用一些证书调用AddAll方法

  1. int[] numbers = { 5, 1, 9, 2, 3, 10, 8, 4, 7, 6 };

  2. WriteLine(AddAll(numbers)); // infers T = int

字典文字(Dictionary Literals)

引入更简单的语法类创建初始化Dictionary对象,而无需指定Dictionary类型名称或类型参数。Dictionary的类型参数使用用于数组类型推断的现有规则确定。

  1. // C# 1..8

  2. var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};

  3. // C# 9

  4. var x = ["foo":4, "bar": 5];

此提议是C#中的字典工作更简单,并删除冗余代码。此外,值得一提的是,在F#和Swift等其他编程语言中也使用了类似的字典语法。

Params Span

到目前为止,在C#中不允许在结构声明中使用no-arg构造函数和字段初始值设定项。在C# 9 中,将删除此限制。StackOverflow example

  1. public struct Rational

  2. {

  3. private long numerator;

  4. private long denominator;


  5. public Rational(long num, long denom)

  6. { /* Todo: Find GCD etc. */ }


  7. public Rational(long num)

  8. {

  9. numerator = num;

  10. denominator = 1;

  11. }


  12. public Rational() // This is not allowed

  13. {

  14. numerator = 0;

  15. denominator = 1;

  16. }

  17. }

连接到 StackOverflow Example

来自官提案的引文,

HaloFour 提交于2017年9月6日 提案 #099 改提议旨在销售阻止声明默认构造函数的语言限制。CLR已经完全支持具有默认构造函数的结构体,并且C#支持使用它们。它们与常量完全无关,并且由于该特征已经存在于CLR基本且表现不同,因此无法与常量相关。

原生大小的数字类型

为本机引入一组新的本机类型(nint,nuint,nfloat,等)‘n’为原生。计划为新数据类型的设计允许一个C#源文件使用32自然或64位存储,具体取决于主机平台类型和编辑设置。

本机类型取决于操作系统

  1. nint nativeInt = 55; take 4 bytes when I compile in 32 Bit host.

  2. nint nativeInt = 55; take 8 bytes when I compile in 64 Bit host with x64 compilation settings.

在xamarin中已存在类似概念。

  • xamarin 原生类型

固定大小的缓冲区

这些提供了一种通用且安全的机制,用于向C#语言声明固定大小的缓冲区。

今天,用户可以在不安全的环境中创建固定大小的缓冲区。然而,这需要用户处理指针,手动执行边界检查,并且只支持一组有限的类型(bool,byte,char,short,int,long,sbyte,ushort,uint,ulong,float和double)。

此功能将使固定大小的缓冲区安全,如下示例所示

可以通过以下方式声明一个安全的固定大小的缓冲区 publicfixedDXGI_RGBGammaCurve[1025];该声明将编译器转化为内部表示,类似于以下内容

  1. [FixedBuffer(typeof(DXGI_RGB), 1024)]

  2. public ConsoleApp1.<Buffer>e__FixedBuffer_1024<DXGI_RGB> GammaCurve;


  3. // Pack = 0 is the default packing and should result in indexable layout.

  4. [CompilerGenerated, UnsafeValueType, StructLayout(LayoutKind.Sequential, Pack = 0)]

  5. struct <Buffer>e__FixedBuffer_1024<T>

  6. {

  7. private T _e0;

  8. private T _e1;

  9. // _e2 ... _e1023

  10. private T _e1024;

  11. public ref T this[int index] => ref (uint)index <= 1024u ?

  12. ref RefAdd<T>(ref _e0, index):

  13. throw new IndexOutOfRange();

  14. }

Uft8字符串文字

它是关于定义一种新类型的Uft8String,如 System.UTF8String myUTF8string="Test String";

based(T)

问题

  1. interface I1

  2. {

  3. void M(int) { }

  4. }


  5. interface I2

  6. {

  7. void M(short) { }

  8. }


  9. interface I3

  10. {

  11. override void I1.M(int) { }

  12. }


  13. interface I4 : I3

  14. {

  15. void M2()

  16. {

  17. base(I3).M(0) // What does this do?

  18. }

  19. }

棘手的部分在于M(short)和M(int)都适用于M(0),但查找规则也说如果我们在再次派生的接口中找到使用的成员,我们忽略来自较少派生继承接口的成员。结合在查找期间未找到覆盖的规则,在查看I3是,我们发现第一件事是I2.M,这是适用的,这意味着I1.M 不会出现在使用成员列表中。 由于我们在上一次会议中得出结论,目标类型中必须存在一个实现,并且I2.M是唯一适用的成员,所写的调用库(I3).M(0)是一个错误,应为I2.M没有在I3中的一个实现

更多信息:

  • https://github.com/dotnet/csharplang/issues/2337

  • https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-02-27.md

概要

你已经阅读了第一个C# 9 的候选功能。正如你看到的,许多新功能受到其他编程语言或编程范例的启发,而不是自我创新,但是好处是大多数候选功能在社区中得到了广泛认可。

原文链接

注:翻译原创

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

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

相关文章

AKS开讲啦! | DevOps with AKS

上周小Phippy搬到了Kube船长船上的Pods里&#xff0c;感觉好极了&#xff0c;那今天我们继续看看Phippy的兴趣爱好哦。探索Kube船上的世界上篇&#xff08;点击回顾&#xff09;小Phippy 搬到了船上的Pods里&#xff0c;感受到了回家般的舒适感&#xff0c;小Phippy希望能发挥一…

把文件隐藏在图片中

一、前言有的时候我们需要把文件给隐藏起来&#xff0c;但是Windows自带的隐藏方式还是很容易被发现的。这时候我们可以选择把文件放在网盘&#xff0c;但这毕竟需要网络。不过&#xff0c;我们可以通过Windows自带的功能&#xff0c;把文件隐藏在图片中。是不是有一种大隐隐于…

.NetCore下使用Polly结合IHttpClientFactory实现聚合服务

在使用微服务的过程中经常会遇到这样的情况&#xff0c;就目前我遇到的问题做下分析情况一&#xff1a;这里服务对于前后端分离情况来说&#xff0c;多使用查询服务&#xff0c;前端直接获取不同服务的数据展示&#xff0c;如果出现其中的服务失败&#xff0c;对业务数据无影响…

你需要了解的有关.NET日期时间的必要信息

引言DateTime数据类型是一个复杂的问题&#xff0c;复杂到足以让你在编写【将日期从Web服务器返回到浏览器】简单代码时感到困惑。ASP.NET MVC 5和 Web API 2/ASP.NETCore 以不同方式序列化日期&#xff0c;这可能会给在一个Web应用程序中同时使用这两个序列化的开发人员带来更…

只需3步,即可将你的Chromium Edge 浏览器设置成中文

最近&#xff0c;Chromium Edge 浏览器推出了添加语言包的功能&#xff0c;于是我们可以轻松将其界面设置成中文的。第1步: 升级浏览器到最新版在Chromium Edge 浏览器的地址栏中输入:edge://settings/help稍等片刻&#xff0c;浏览器会自行升级到最新版。第2步: 将Language se…

【北京】线下活动 | Azure SQL Database Managed Instance发布会

6/12/2019 | 8.30 AM - 1.30 PM微软大厦一号楼一层故宫会议室N丹棱街5号 海淀区 北京市S尊敬的客户感谢您一直以来对微软的支持&#xff01;诚挚地邀请您参加微软Azure SQL Database Managed Instance &#xff08;SQL Database托管实例&#xff09;在中国北京的发布会。SQL Da…

ASP.Net Core MVC 发生二次请求

Bug回忆录昨天搭建新框架的时候&#xff0c;遇到一个很奇怪的“Bug”&#xff0c;每次请求都会触发两次Aciton&#xff0c;举例子吧&#xff0c;Demo&#xff1a;_Layout.cshtmlHomeControllerIndex.cshtml<h1>Hi, Im index page.</h1>最简单不过的代码&#xff0c…

DDD战略设计相关核心概念的理解

前言本文想再讨论一下关于领域、业务、业务模型、解决方案、BC、领域模型、微服务这些概念的含义和关系。初衷是我发现现在DDD领域建模以及解决方案落地过程中&#xff0c;常常对这些概念理解不清楚或者有歧义&#xff0c;导致我们不知道如何运用这些概念来落地我们的软件。领域…

Visual Studio容器项目工程化心得

引言  关注博主的网友会看到我使用ASP.NET Core 容器化部署企业级项目的过程&#xff0c; 回想到开发过程中&#xff0c;鄙人有一些工程化心得&#xff0c; 分享给同学们。项目工程化因为本项目涉及单元测试Project、容器化部署、本地化的sqlite数据库&#xff0c;nlog日志&a…

Insider Dev Tour 2019 | 以技术之力,展现传承魅力

世界原本是一个漆黑的山洞的大小&#xff0c;一个“胆大妄为”的人燃起火把&#xff1b;世界原本是一个孤岛的轮廓&#xff0c;一个“野心勃勃”的人扬帆起航&#xff1b;如今&#xff0c;世界的版图已经清晰&#xff0c;是什么让我们走出黑暗与闭塞&#xff0c;从未放下对未知…

.NET 之 ORM 性能评测

Why你应该总能听到某ORM性能比Dapper高你应该有如下疑问&#xff1a;基准测试是否权威基准测试的方式是否合理基准测试的标准是否能够统一统一基准测试标准/规范如何进行姿势正确的性能测试相信大家对 Dapper 的性能&#xff0c;以及基准测试的权威性是没有疑问的&#xff08;否…

CF817E Choosing The Commander 01tire 贪心

看到集合和异或&#xff0c;可以想到01tire(但是我没有想到)。 让后就可以对于每次插入和删除一个数&#xff0c;都在01tire树上操作即可。让后记录一下到当前位(当然是从高位到低位啦)有相同前缀的数的个数。例如样例建图出来大概是这样的&#xff1a; 可以看到从编号为2的点开…

不断进化的分支和需求管理

昨天有朋友在公众号私信问我几个关于代码分支管理的问题&#xff0c;这几个问题是我去年写的《在团队中使用GitLab中的Merge Request工作模式》一文结尾时抛出的几个问题&#xff1a;如果系统上线后有紧急Bug需要处理&#xff0c;这个流程应该怎样去调整&#xff1f;每个任务都…

CF56E Domino Principle 树状数组 + 简单dp

一个比较简单的题&#xff0c;但是我还是没做出来(哭。 很容易想到从后往前做&#xff0c;所以我们可以维护一个dp数组f&#xff0c;f(i)表示到第i个牌倒下能达到的最远距离。 f直接倒着跑&#xff0c;每次取[x,xh−1][x,xh-1][x,xh−1]的最大值即可&#xff0c;可以用线段树比…

基于Docker的Consul服务发现集群搭建

在去年的.NET Core微服务系列文章中&#xff0c;初步学习了一下Consul服务发现&#xff0c;总结了两篇文章。本次基于Docker部署的方式&#xff0c;以一个Demo示例来搭建一个Consul的示例集群&#xff0c;最后给出一个HA的架构示范&#xff0c;也会更加贴近于实际应用环境。一、…

Hills And Valleys CodeForces - 1467B 思维

给你一个数组&#xff0c;最多可以修改一个数&#xff0c;问最少的山峰和山谷数量之和。 小菜鸡做了一年。 一上来想猜个结论&#xff0c;让每个数等于其相邻的两个数&#xff0c;看了题解之后也证明的正确性&#xff0c;当时直接写就没后面这么多事了。 但是命运让我分情况讨…

[译]使用LazZiya.ExpressLocalization开发多语言支持的ASP.NET Core 2.x项目

介绍开发多语言支持的ASP.NET Core 2.x Web应用程序需要大量的基础架构设置&#xff0c;并且耗费时间和精力。这篇文章&#xff0c;我们将使用LazZiya.ExpressLocalization nuget包一步本地化支持。背景大多数网络应用程序都是基于网址的本地化。因此我们可以在网址中看到所选的…

2019 ICPC World Finals Problem B. Beautiful Bridges

2019 ICPC World Finals Problem B. Beautiful Bridges Solution 太菜了&#xff0c;sbsbsb题调了一个下午。 首先有一个显然的O(n3)O(n^3)O(n3)的dpdpdp&#xff0c;令fif_ifi​表示最后一个桥柱在iii的最小代价&#xff0c;枚举上一个桥柱jjj&#xff0c;因为地面超过桥拱…

ac 梦幻布丁 启发式合并

题意&#xff1a;中文题。 对于每种颜色&#xff0c;我们都可以看成一个集合。让后把一种颜色变成另一种颜色就转换成了把两个集合的合并问题。显然我们有一个复杂度为O(NlogN)O(NlogN)O(NlogN)的启发式合并能完美的解决这个问题。 解决合并问题了&#xff0c;现在需要解决如何…

VS Code 1.35 发布!全新 logo 来临,远程开发进入稳定版

近期&#xff08; 北京时间 2019 年 6 月 6 日 &#xff09;&#xff0c;微软发布了 Visual Studio Code 1.35 版本&#xff0c;带来了众多更新。全新的 logo全新的图标来啦~ 这一次的图标更新历时两个月&#xff0c;VS Code 团队倾听了用户们的反馈。大家对新图标还喜欢吗&…