C# 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 如下,允许在命名空间的声明前面,添加一组语句,且只允许有一个编译单元(可以认为是一个源文件)拥有这种语句:

  1. compilation_unit
  2. : extern_alias_directive* using_directive* global_attributes? statement* namespace_member_declaration*
  3. ;

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

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

以上代码会被翻译为:

  1. static class $Program
  2. {
  3. static void $Main(string[] args)
  4. {
  5. System.Console.WriteLine("Hi!");
  6. }
  7. }

可以看到,WriteLine语句被自动的包在了一个类和 Main 方法里面。
自动生成的 Main 方法的返回值也会根据是否异步以及是否有返回值来变化,例如:

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

会被翻译为:

  1. static class $Program
  2. {
  3. static async Task<int> $Main(string[] args)
  4. {
  5. await System.Threading.Tasks.Task.Delay(1000);
  6. System.Console.WriteLine("Hi!");
  7. return 0;
  8. }
  9. }

各种场景

  • 支持在 using 语句后面:
  1. using System;
  2. Console.Write("Hi!");

会被翻译为:

  1. using System;
  2. static class $Program
  3. {
  4. static void $Main(string[] args)
  5. {
  6. Console.Write("Hi!");
  7. }
  8. }
  • 也可以加上本地函数:
  1. local();
  2. void local() => System.Console.WriteLine(2);
  • 可以与其它代码共存,例如类的声明:
  1. Type.M();
  2. static class Type
  3. {
  4. public static void M()
  5. {
  6. System.Console.WriteLine("Hi!");
  7. }
  8. }

稍微复杂一点的:

  1. await using (var x = new C())
  2. {
  3. System.Console.Write("body ");
  4. }
  5. class C : System.IAsyncDisposable, System.IDisposable
  6. {
  7. public System.Threading.Tasks.ValueTask DisposeAsync()
  8. {
  9. System.Console.Write("DisposeAsync");
  10. return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
  11. }
  12. public void Dispose()
  13. {
  14. System.Console.Write("IGNORED");
  15. }
  16. }
  • 同时兼容了using alias的语法
  1. using alias1 = Test;
  2. string Test() => ""1"";
  3. System.Console.WriteLine(Test());
  4. class Test {}
  5. delegate Test D(alias1 x);
  6. namespace N1
  7. {
  8. using alias2 = Test;
  9. delegate Test D(alias2 x);
  10. }
  • 也可以同时与显示的 Main 方法声明在一起,只不过显示的Main方法会被忽略掉并提示一个警告
  1. using System;
  2. using System.Threading.Tasks;
  3. System.Console.Write("Hi!");
  4. class Program
  5. {
  6. static void Main() // warning CS7022: The entry point of the program is global code; ignoring 'Program.Main()' entry point
  7. {
  8. Console.Write("hello");
  9. }
  10. }

限制

  • 不支持在多个编译单元下拥有顶级语句:
  1. // file1.cs
  2. System.Console.WriteLine("1"); // error CS9001: Only one compilation unit can have top-level statements.
  3. // file2.cs
  4. System.Console.WriteLine("2"); // error CS9001: Only one compilation unit can have top-level statements.
  • 不能放在类的内部
  1. class Test
  2. {
  3. System.Console.WriteLine("Hi!"); // ERROR
  4. }
  • 不能放在命名空间的内部
  1. namespace Test
  2. {
  3. System.Console.WriteLine("Hi!"); // ERROR
  4. }
  • 要么所有分支都有返回值,要么都没有
  1. System.Console.WriteLine();
  2. if (args.Length == 0)
  3. {
  4. return 10; // error CS0161: 不是所有代码分支都有返回值
  5. }
  • 虽然可以可以与类声明一起写,但是在类中是无法调用到 Main 方法 args 入参的,因为编译时会编译为两个类
  1. System.Console.WriteLine(args);
  2. class Test
  3. {
  4. void M()
  5. {
  6. System.Console.WriteLine(args); // ERROR
  7. }
  8. }
  • 自然,你也不能用 args 来命名本地函数
  1. args(1);
  2. void args(int x) // ERROR
  3. {}

参考

[Proposal: Simplified Null Argument Checking]
[Unit test: NullCheckedParameterTests.cs]
[LDM-2019-07-10.md]

C# 9.0 新特性预览 - 顶级语句的更多相关文章

  1. C# 9.0 新特性预览 - init-only 属性

    C# 9.0 新特性预览 - init-only 属性 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章 ...

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

    C# 9.0 新特性预览 - 类型推导的 new 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大 ...

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

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

  4. Vue.js 3.0 新特性预览

    总结起来,Vue 3 以下方面值得我们期待 : 更快 更小 更易于维护 更多的原生支持 更易于开发使用 完整的PPT:docs.google.com/presentatio… Evan 和 Vue 团 ...

  5. C#9.0新特性之四:顶级程序语句(Top-Level Programs)

    1 背景与动机 通常,如果只想用C#在控制台上打印一行"Hello World!",这可不是Console.WriteLine("Hello World!"); ...

  6. Windows Phone 8.1SDK新特性预览

    前言    Windows Phone 8.1的预览版将在近期推送,WP 8.1的SDK也已经进入到RC阶段,可以从这里安装.本次更新的SDK被直接集成到了VS2013Update2里面,不再是单独的 ...

  7. avalon1.3的新特性预览

    avalon1.2的性能优化风暴很快就告一段落,入职也快一个月了,许多乱七八糟的事也少了下来,估计未来一个月会有许多好东呈现给大家. 首先是一个性能检测工具.由于MVVM是将原本由人脑干的事,转到各种 ...

  8. Office 2016 正式发布——新特性预览

    今天微软又发生了一件大事!Windows Office 2016正式发布,这标志着Windows Office 又达到了一个新的里程碑! 全新的Office 发布为Office 365 用户带来了新的 ...

  9. CSS3_新特性预览

    一.强大的CSS选择器 以前我们通常用class. ID 或 tagname 来选择HTML元素,CSS3的选择器强大的难以置信.  它们可以减少在标签中的class和ID的数量更方便的维护样式表.更 ...

随机推荐

  1. COS418, Distributed System, Go Language

    本博客是MIT的分布式系统课程的课后作业Cos418的GO语言实现思路.由于时间有限,目前只实现了assignment1~2. 在common.go中设置debugEnabled = true,go ...

  2. ReplayingDecoder 解码器:别以为我有多厉害,也只不过是使用了一下装饰器模式而已~

    原文地址 一.设计模式为啥老是用不好? 想要写出更屌的代码,提高代码的健壮性和可扩展性,那么设计模式可谓是必学的技能. 关于学习设计模式,大家可能都觉得设计模式的概念太过于抽象,理解起来有点费劲:又或 ...

  3. 类的加载,链接和初始化——1运行时常量池(来自于java虚拟机规范英文版本+本人的翻译和理解)

    加载(loading):通过一个特定的名字,找到类或接口的二进制表示,并通过这个二进制表示创建一个类或接口的过程. 链接:是获取类或接口并把它结合到JVM的运行时状态中,以让类或接口可以被执行 初始化 ...

  4. Selenium使用cookis登录,并临时将cookis存储在本地【shelve数据库】

    Python中自带了一个shelve库,可以帮助我们存储一些少量的数据. shelve数据库类似redis,是以[键值对]的方式进行数据的存储,有点像"字典"这种数据结构,存储在本 ...

  5. Ellxir

    API: elixir https://hexdocs.pm/elixir/Module.html#content API: erlang http://www.cnerlang.com/api.ht ...

  6. 热更新 && 增量更新

    Unity中SLua.Tolua.XLua和ILRuntime效率评测 http://blog.csdn.net/u011467512/article/details/72716376 如何阅读lua ...

  7. unity webview

    uniwebview http://uniwebview.onevcat.com/manual Unity3D研究院之在Android中打开WebView(三十) http://www.xuanyus ...

  8. 初学WebGL引擎-BabylonJS:第0篇-起因

    学习WebGL的BabylonJS是在一次偶然的情况下进行的,主要为了满足个人对全栈开发的欲望. 言归正传,下面开始简单说说相关过程 WebGL是什么?WebGL是基于html的客户端页面技术,基于h ...

  9. Unity图文混排

    http://blog.csdn.net/akof1314/article/details/49028279 http://blog.csdn.net/akof1314/article/details ...

  10. 【jmespath】—2. 进阶 List and Slice Projections

    Projections翻译的话说实话我也不知道翻成什么比较准确,姑且就叫"投影"吧,不过带来的功能确实非常的强大.好用. 首先,我先说下我的理解: 通配符 * 通配符生成的是一个l ...