C# 9.0 新特性預(yù)覽 頂級語句
轉(zhuǎn)自:Rwing cnblogs.com/Rwing/p/csharp-9-0
前言
隨著 .NET 5 發(fā)布日期的日益臨近,其對應(yīng)的 C#新版本已確定為 C# 9.0,其中新增加的特性(或語法糖)也已基本鎖定,本系列文章將向大家展示它們。
目錄
《C# 9.0 新特性預(yù)覽 - 類型推導的 new》
《C# 9.0 新特性預(yù)覽 - 空參數(shù)校驗》
《C# 9.0 新特性預(yù)覽 - 頂級語句》
《C# 9.0 新特性預(yù)覽 - Record 類型》
《C# 9.0 新特性預(yù)覽 - 模式匹配的改善》
《C# 9.0 新特性預(yù)覽 - 源代碼生成器》
《C# 9.0 新特性預(yù)覽 - 其他小的變化》
頂級語句 (Top-level statements)
頂級語句這個名字看起來不是那么直觀,或許它的曾用名更好一些:Simple Programs,簡單程序。
目的
想必大家都知道,即使是最簡單的 C#程序,也會有一定量的繁文縟節(jié),因為最少也需要一個 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 方法的返回值也會根據(jù)是否異步以及是否有返回值來變化,例如:
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!");
}
}
也可以加上本地函數(shù):
local();
void local() => System.Console.WriteLine(2);
可以與其它代碼共存,例如類的聲明:
Type.M();
static class Type
{
public static void M()
{
System.Console.WriteLine("Hi!");
}
}
稍微復(fù)雜一點的:
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");
}
}
限制
不支持在多個編譯單元下?lián)碛许敿壵Z句:
// 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.
不能放在類的內(nèi)部
class Test
{
System.Console.WriteLine("Hi!"); // ERROR
}
不能放在命名空間的內(nèi)部
namespace Test
{
System.Console.WriteLine("Hi!"); // ERROR
}
要么所有分支都有返回值,要么都沒有
System.Console.WriteLine();
if (args.Length == 0)
{
return 10; // error CS0161: 不是所有代碼分支都有返回值
}
雖然可以可以與類聲明一起寫,但是在類中是無法調(diào)用到 Main 方法 args 入?yún)⒌?,因為編譯時會編譯為兩個類
System.Console.WriteLine(args);
class Test
{
void M()
{
System.Console.WriteLine(args); // ERROR
}
}
自然,你也不能用 args 來命名本地函數(shù)
args(1);
void args(int x) // ERROR
{}
參考
[Proposal: Simplified Null Argument Checking]
[Unit test: NullCheckedParameterTests.cs]
[LDM-2019-07-10.md]
- EOF -
版權(quán)聲明
本文來源:博客園博主“Rwing”,版權(quán)歸原作者所有,如有侵權(quán)請后臺聯(lián)系小編刪除。
資源分享
謝謝您的支持,需要任何資源,只需要在公眾號后臺回復(fù)對應(yīng)數(shù)字即可:
01:dotnet
02:java
03:android
04:C++
05:qt
06:react
沒有的資源或資源鏈接失效,請給我留言或加我微信。
另:大部分資源可在我的網(wǎng)站搜索哦:https://dotnet9.com
