C# 10.0 向 C# 语言添加了以下功能和增强功能:

1、record struct(记录结构)

C# 9 有一个新的数据类型,叫做记录(Record)。这个类型是一种特殊的引用类型,我们只需要给出一个东西的具体属性,就可以自动为这个类型生成指定的比较器(Equals 方法、比较运算符 operator == 和 operator !=、GetHashCode 方法,甚至是 ToString 方法等等)。

举个例子,我们可以这么写:

public sealed record Point(int X, int Y);

这就等价于一个类 Point,然后生成 X 和 Y 属性,以及相关的方法:

public sealed class Point
{
public int X { get; init; }
public int Y { get; init; } public override string ToString() => $"Point {{ X = {X}, Y = {Y} }}";
public override bool Equals(object? obj) => obj is Point p && p.X == X && p.Y == y;
public override int GetHashCode() => HashCode.Combine(X, Y); public static bool operator ==(Point l, Point r) => l.Equals(r);
public static bool operator !=(Point l, Point r) => !(l == r);
}

这样的东西。你看看,就写一句话就能生成一系列的内容,是不是很方便。

不过,Point 类型就俩属性,显然没有必要定义成类,因为它太轻量级了。因此,C# 10 开始允许结构记录类型。

public record struct Point(int X, int Y);

这样就好比把前文的 sealed class 改写成 struct。因此 C# 10 开始允许结构的记录类型,所以更轻量级,灵活度更高了。当然,C# 10 依然允许引用类型(类)的记录类型,你可以使用 record 或者 record class 来表示一个类的记录类型。

首先自然是 record struct,解决了 record 只能给 class 而不能给 struct 用的问题:
record struct Point(int X, int Y);
用 record 定义 struct 的好处其实有很多,例如你无需重写 GetHashCode 和 Equals 之类的方法了。
sealed record ToString 方法
之前 record 的 ToString 是不能修饰为 sealed 的,因此如果你继承了一个 record,相应的 ToString 行为也会被改变,因此这是个虚方法。
但是现在你可以把 record 里的 ToString 方法标记成 sealed,这样你的 ToString 方法就不会被重写了。

2、struct 无参构造函数

struct S0
{
object x = null;
object y;
// ok
} struct S1
{
object x = null;
object y;
S() { } // error: field 'y' must be assigned
} struct S2
{
object x = null;
object y;
S() : this(null) { } // ok
S(object y) { this.y = y; } // ok
}
struct Foo
{
public int X;
public Foo() { X = 1; }
}

一直以来 struct 不支持无参构造函数,现在支持了:

这个例子展示了无参构造器的使用方式。显然,跟引用类型是基本一样的,只是多了一点:如果你不定义的话,默认会生成一个无参构造器(S0 结构,y 会被自动赋值默认数值 default(object),也就是 null);但一经定义,就必须给所有没有赋值的字段和属性赋值。

当然,此时的构造器既然允许自定义了,这样就使得构造器可以定义和修改访问修饰符了。如果访问修饰符设置为 private 的话,那么外部就无法使用 new 来实例化该类型的对象了。这一点和引用类型还是一样的。

但是使用的时候就要注意了,因为无参构造函数的存在使得 new struct() 和 default(struct) 的语义不一样了,例如 new Foo().X == default(Foo).X 在上面这个例子中将会得出 false

2.1、结构的字段初始化器

可以看到,这个特性一旦出现,就相当于诞生了另外一个特性:结构的字段初始化器。C# 早期同样是不允许你给字段设置默认数值的;相反,你必须在构造器里赋值,还不能是默认的无参构造器里。

2.2、default(T) 表达式

另外,由于值类型和引用类型的默认数值不同的关系,定义了无参构造器必然会影响到它的默认数值
default(T) 表达式。实际上真的是这样吗?并不是。还是拿 Point
类型举例。即使你给出了默认构造器的调用,default(Point) 依旧还是原始数据的原始数据类型的默认数值构造成的实例的结果。

readonly struct Point
{
public Point() { X = int.MinValue; Y = int.MinValue; } public int X { get; }
public int Y { get; }
}

那么,default(Point) 还是 Point { X = 0, Y = 0 },而不是 Point { X = -2147483647, Y = -2147483647 } 的这个新结果。

我们把“原始数据的原始数据类型的默认数值构造成的实例”叫做零初始化实例(Zeroed
Instance),那么,default(T)
的定义就可以缩减为“该类型的零初始化实例”;换句话说,该类型的零初始化实例就是这个值类型的默认数值。那么,使用 default
表达式的时候,就算你定义了无参构造器,编译器也会始终忽略它。

3、常量字符串插值

C# 6 诞生的内插字符串并不能直接当成常量使用。举个例子:
const string A = "Sunnie";
const string B = $"Hello, {A}"; // Here

这个写法对吗?从道理上是说得通的。但是,这个写法不对。因为内插字符串没有得到编译器认为其是常量的允许,因此 B 这里会产生编译器错误。所以,你不得不改成加法运算

const string B = "Hello, " + A; // OK. 

C# 10 开始允许这一点,内插字符串也可以认为是常量了;当然前提是,内插的部分也都得是常量才行;而且内插的对象必须也得是 string 才行。

4、内插字符串处理程序

C# 10 增加了对自定义内插字符串处理程序的支持。 内插字符串处理程序是处理内插字符串中的占位符表达式的一种类型。 如果没有自定义处理程序,占位符的处理方式与 String.Format 类似。 每个占位符的格式设置为文本,然后将各组成部分串联起来,形成最终的字符串。

详细请看:https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/tutorials/interpolated-string-handler

5、全局的 using

可将 global 修饰符添加到任何 using 指令,以指示编译器该指令适用于编译中的所有源文件。 这通常是项目中的所有源文件。

global using IntegerList = System.Collections.Generic<int>;

那么,整个项目就都可以使用这个 IntegerList 了。

6、命名空间

C# 10 开始你将能够在文件顶部指定该文件的 namespace,一个源文件只能包含一个namespace MyProject;声明。而不需要写一个 namespace 然后把其他代码都嵌套在大括号里面,毕竟绝大多数情况下,我们在写代码时一个文件里确实只会写一个 namespace,这样可以减少一层嵌套也是很不错的。

但是,原始的写法是允许嵌套命名空间和并排命名空间的,而一旦使用 namespace 指令后,就不可在文件里多次声明嵌套或并行的命名空间了。

namespace MyProject;

class MyClass
{
// ...
}

7、元组表达式里内联变量定义

这句话不好理解。举个例子。
int age;
(name, age) = student;
假如,name 是本身就有的东西(它可能是属性,或者是字段,或者是临时变量),而 age 仅仅是一个临时变量。如果你要把右侧的 student 变量解构了的话,由于 age 的定义变量语句无法写到赋值语句里面去,所以只能分开成两行书写。
C# 10 将允许你内嵌定义语句到值元组赋值的语句里去。
(name, int age) = student;
这样就合二为一了。name 照旧赋值,而 age 则完成了定义变量和赋值两个操作,且都在这一行里就可以完成。方便了不少。

lambda 改进

这个改进可以说是非常大,我分多点介绍。

1、支持 attributes

lambda 可以带 attribute 了:

f = [Foo] (x) => x; // 给 lambda 设置
f = [return: Foo] (x) => x; // 给 lambda 返回值设置
f = ([Foo] x) => x; // 给 lambda 参数设置

2、支持指定返回值类型

此前 C# 的 lambda 返回值类型靠推导,C# 10 开始允许在参数列表最前面显示指定 lambda 类型了:

f = int () => 4;

3、支持 ref 、in 、out 等修饰

f = ref int (ref int x) => ref x; // 返回一个参数的引用

4、头等函数

函数可以隐式转换到 delegate,于是函数上升至头等函数:

void Foo() { Console.WriteLine("hello"); }
var x = Foo;
x(); // hello

5、自然委托类型

lambda 现在会自动创建自然委托类型,于是不再需要写出类型了。

var f = () => 1; // Func<int>
var g = string (int x, string y) => $"{y}{x}"; // Func<int, string, string>
var h = "test".GetHashCode; // Func<int>

CallerArgumentExpression

现在,CallerArgumentExpression 这个 attribute 终于有用了。借助这个 attribute,编译器会自动填充调用参数的表达式字符串,例如:

void Foo(int value, [CallerArgumentExpression("value")] string? expression = null)
{
    Console.WriteLine(expression + " = " + value);
}

当你调用 Foo(4 + 5) 时,会输出 4 + 5 = 9。这对测试框架极其有用,因为你可以输出 assert 的原表达式了:

static void Assert(bool value, [CallerArgumentExpression("value")] string? expr = null)
{
    if (!value) throw new AssertFailureException(expr);
}

tuple 支持混合定义和使用

比如:

int y = 0;
(var x, y, var z) = (1, 2, 3);

于是 y 就变成 2 了,同时还创建了两个变量 x 和 z,分别是 1 和 3 。

8、C#新写法,默认文件内容都是写在Main函数中,C#支持本地函数。所以里面文件中函数其实是本地函数

 
Console.WriteLine("该程序接收多个参数 用空格 来做参数分隔符");
Console.WriteLine($"main函数参数agrs 的长度{args.Length} ");
int i = 1;
foreach (var s1 in args)
{
Console.WriteLine($"参数{i++}:{s1}"); } Console.WriteLine(args);
Console.ReadKey();
Count();
void Count()
{ Console.WriteLine("sdfsdf"); } void Count1(string ser)
{ Console.WriteLine("sdfsdf"); }

通过IL反编译后结果

C#10 新功能的更多相关文章

  1. What's new in Windows 10 Enterprise with Microsoft Edge.(Windows 10 新功能)

    What's new in Windows 10 Enterprise with Microsoft Edge --带有Edge浏览器的Windows 10 企业版的新功能 本文摘录自公司群发邮件, ...

  2. Windows 10新功能

    Windows 10 中面向开发人员的新增功能 Windows 10 及新增的开发人员工具将提供新通用 Windows 平台支持的工具.功能和体验.在 Windows 10 上安装完工具和 SDK后, ...

  3. Windows 10 新功能

    一.与 Cortana 集成的便笺 借助便笺,你可捕捉并保存绝妙创意或记录重要细节.便笺现已与 Cortana 集成,让你能够设置整个设备中的提醒. (一)   先来了解一下微软小娜Cortana. ...

  4. .NET6系列:C#10新功能预览

    系列目录     [已更新最新开发文章,点击查看详细] 2021年4月19日微软发布公告称将于今年夏季发布首款64位的 Visual Studio 2022,2021年5月20日又发布了 Visual ...

  5. Java 17 将要发布,补一下 Java 13 中的新功能

    本文章属于Java 新特性教程 系列,已经收录在 Github.com/niumoo/JavaNotes ,点个赞,不迷路. 自从 Oracle 调整了 Java 的版本发布节奏之后,Java 版本发 ...

  6. iOS 10正式发布:十大新功能,更注重人性化

    6月14日凌晨消息,苹果公司举行2016年WWDC全球开发者大会,介绍了watch OS.tv OS.OS X以及iOS 10系统的新特性. 据苹果介绍,iOS 10在锁屏.Siri.地图等十个各方面 ...

  7. Win 10更新版1709有哪些新功能值得关注!

    windows 10秋季创意者更新版1709发布已经有段时间了,也有很多用户选择升级这次更新的系统.那么,这次Win 10 更新版1709有哪些新功能值得关注呢?下面,一起随主机吧来看一看吧! 1. ...

  8. RAD Studio 10.3.2七大新功能介绍

    RAD Studio 10.3.2七大新功能 Delphi支持macOS 64位应用的开发. C++Builder中Windows 64位平台支持C ++ 17特性. C ++ LSP 代码洞察改进. ...

  9. Windows 10 20H1 2004新功能

    Windows 10的年度更新版本20H1即将问世.目前可以从insider preview渠道中获得.这个版本中看上去对搜索功能做了不小的改进.包括搜索的磁盘占用率以及搜索的一些展示方式. 其它的一 ...

随机推荐

  1. 实习之bii--总体感受体验

    在bii实习了一个暑假,感受收获都不少,记录一下. 首先当时面试时其实说的比较多的是sdn,结果来了以后主要在搞DNS,介绍一下所做的工作为何吧.bii名为北京下一代互联网工程中心,由于IPV6的逐渐 ...

  2. golang中goroutine池的使用

    1. 概念本质上是生产者.消费者模型可以有效的控制goroutine数量,防止暴涨案例:生成一个随机数,计算该随机数每一个数字相加的和,例如:123:1+2+3=6主协程负责生产数据发送到待处理通道中 ...

  3. 测试开发实战[提测平台]19-Echarts图表在项目的应用

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 在图表统计展示方面,笔者目前使用过的两种开源,分别是 Echats 和 G2Plot 组件,从个人使用上来讲前者应用更广.自定义开发更灵活 ...

  4. Python学习笔记之读取文件、OS模块、异常处理、with as语法示例

    转:https://m.sogou.com/web/id=4c468b90-3f64-418c-acf8-990b5fe2a757/keyword=python%20os%E6%A8%A1%E5%9D ...

  5. 多线程中sleep方法,简单介绍。

    一 是什么? package com.aaa.threaddemo; /* * 多线程中的sleep方法? * sleep 隶属于Thread的方法,顾名思义,让线程睡一会. 1 public sta ...

  6. 线程终止的四种方式,interrupt 方法使用的简单介绍。

    一 正常结束. package com.aaa.threaddemo; /* 一 终止线程的四种方式? * 程序运行结束,线程终止. * */ public class ThreadTerminati ...

  7. linux 常用命令。

    /* Linux常用命令? 1 查看 ls             展示当前目录下的可见文件   ls -a         展示当前目录下所有的文件(包括隐藏的文件)   ls -l(ll)     ...

  8. 【C++】输入输出

    缓冲 C++ 的输入输出均通过缓冲区来实现.缓冲区主要是为了解决速度不匹配的问题. cin 阻塞输入.当输入缓存中无字符时则等待用户输入. 输入缓冲 输入缓冲是一种行缓冲.在输入数据只要没有碰到换行符 ...

  9. Android 实用开源库(不定期更新)

    ZXing 极其好用的二维码开源库. GayHub:https://github.com/zxing/zxing MPAndroidChart MPAndroidChart 是 Android 一个强 ...

  10. memcached 测试代码

    转载请注明来源:https://www.cnblogs.com/hookjc/ #include<stdio.h> #include <iostream> #include & ...