C# 9.0 新特性预览 顶级语句

共 4218字,需浏览 9分钟

 ·

2020-10-15 19:43






转自:Rwing


cnblogs.com/Rwing/p/csharp-9-0



前言




随着 .NET 5 发布日期的日益临近,其对应的 C#新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们。




目录




C# 9.0 新特性预览 - 类型推导的 new




C# 9.0 新特性预览 - 空参数校验




C# 9.0 新特性预览 - 顶级语句




C# 9.0 新特性预览 - Record 类型




C# 9.0 新特性预览 - 模式匹配的改善




C# 9.0 新特性预览 - 源代码生成器




C# 9.0 新特性预览 - 其他小的变化




顶级语句 (Top-level statements)




顶级语句这个名字看起来不是那么直观,或许它的曾用名更好一些:Simple Programs,简单程序。




目的




想必大家都知道,即使是最简单的 C#程序,也会有一定量的繁文缛节,因为最少也需要一个 Main 方法。这似乎妨碍了语言的学习和程序的清晰度。




因此,这个特性的最主要目的就是为了初学者和代码的清晰度,让书写 C# 程序可以变得更轻松。




语法




语法 Spec 如下,允许在命名空间的声明前面,添加一组语句,且只允许有一个编译单元(可以认为是一个源文件)拥有这种语句:




compilation_unit
: extern_alias_directive* using_directive*
global_attributes? statement* namespace_member_declaration* ;



Spec 比较难懂,我们直接来看示例:简单来说,就是允许在源文件中直接书写代码语句而不用写 Main 方法:




System.Console.WriteLine("Hi!");



以上代码会被翻译为:




static class $Program
{
static void $Main(string[] args)
{
System.Console.WriteLine("Hi!");
}
}




可以看到,WriteLine语句被自动的包在了一个类和 Main 方法里面。


自动生成的 Main 方法的返回值也会根据是否异步以及是否有返回值来变化,例如:




await System.Threading.Tasks.Task.Delay(1000);
System.Console.WriteLine("Hi!");
return 0;




会被翻译为:




static class $Program
{
static async Task

$Main(string[] args)

{


await System.Threading.Tasks.Task.Delay(
1000);

System.Console.WriteLine(
"Hi!");


return
0;

}

}



各种场景





  • 支持在 using 语句后面:





using System;
Console.Write("Hi!");




会被翻译为:




using System;
static class $Program
{
static void $Main(string[] args)
{
Console.Write("Hi!");
}
}





  • 也可以加上本地函数:





local();
void local() => System.Console.WriteLine(2);




可以与其它代码共存,例如类的声明:




Type.M();
static class Type
{
public static void M()
{
System.Console.WriteLine("Hi!");
}
}




稍微复杂一点的:




await using (var x = new C())
{
System.Console.Write("body ");
}
class C : System.IAsyncDisposable, System.IDisposable
{
public System.Threading.Tasks.ValueTask DisposeAsync()
{
System.Console.Write("DisposeAsync");
return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
}
public void Dispose()
{
System.Console.Write("IGNORED");
}
}





  • 同时兼容了using alias的语法





using alias1 = Test;
string Test() => ""1"";
System.Console.WriteLine(Test());
class Test {}
delegate Test D(alias1 x);
namespace N1
{
using alias2 = Test;
delegate Test D(alias2 x);
}





  • 也可以同时与显示的 Main 方法声明在一起,只不过显示的Main方法会被忽略掉并提示一个警告





using System;
using System.Threading.Tasks;
System.Console.Write("Hi!");
class Program
{
static void Main() // warning CS7022: The entry point of the program is global code; ignoring 'Program.Main()' entry point
{
Console.Write("hello");
}
}



限制





  • 不支持在多个编译单元下拥有顶级语句:





// file1.cs
System.Console.WriteLine("1");
// error CS9001: Only one compilation unit can have top-level statements.

// file2.cs
System.Console.WriteLine("2");
// error CS9001: Only one compilation unit can have top-level statements.





  • 不能放在类的内部





class Test
{
System.Console.WriteLine("Hi!"); // ERROR
}





  • 不能放在命名空间的内部





namespace Test
{
System.Console.WriteLine("Hi!"); // ERROR
}





  • 要么所有分支都有返回值,要么都没有





System.Console.WriteLine();
if (args.Length == 0)
{
return 10; // error CS0161: 不是所有代码分支都有返回值
}





  • 虽然可以可以与类声明一起写,但是在类中是无法调用到 Main 方法 args 入参的,因为编译时会编译为两个类





System.Console.WriteLine(args);
class Test
{
void M()
{
System.Console.WriteLine(args); // ERROR
}
}





  • 自然,你也不能用 args 来命名本地函数





args(1);
void args(int x) // ERROR
{}






参考




[Proposal: Simplified Null Argument Checking]


[Unit test: NullCheckedParameterTests.cs]


[LDM-2019-07-10.md]




- EOF -







版权声明









本文来源:博客园博主“Rwing”,版权归原作者所有,如有侵权请后台联系小编删除。








资源分享





谢谢您的支持,需要任何资源,只需要在公众号后台回复对应数字即可:


01:dotnet
02:java
03:android
04:C++
05:qt
06:react

没有的资源或资源链接失效,请给我留言或加我微信。
另:大部分资源可在我的网站搜索哦:https://dotnet9.com










浏览 33
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报