C#9.0新特性详解——顶级程序语句(Top-Level Programs)

作者:码客风云 时间:2023-07-05 18:46:03 

1 背景与动机

通常,如果只想用C#在控制台上打印一行“Hello World!”,这可不是Console.WriteLine("Hello World!");一条语句就可以搞定的,还涉及到其他必要基础代码(如定义类和入口函数Main),例如下面:


using System;
class Program
{
 static void Main()
 {
   Console.WriteLine("Hello World!");
 }
}

就打印一句“Hello World!”,就这么多代码。这个不仅对于初学者来说麻烦,而且使得代码凌乱,并且增加了缩进层级。为了解决这些问题,就提出了顶级代码语句这个新特性。

2 顶级语句

2.1 介绍

在C#9.0中,将Class的定义和主函数Main的声明省略掉,只写出你的核心业务代码,就成了顶级语句。上面这段代码,我们可以用顶级语句写为:


using System;

Console.WriteLine("Hello World!");

这样,代码简洁清晰了很多,易于初学者理解。是不是有点写Python的感觉?当然,任何语句都是允许的。如果你想返回值,你可以那样做;你想用await,也可以那样做;如果你想访问命令行参数,args也是可用的;你想使用本地函数,也是可以的。

虽然可以使用任何代码,但是有一些规则要求必须遵守:

  • 顶级语句必须放在using语句代码后面

  • 顶级语句必须用在任何类型或者命名空间声明的前面

  • 顶级语句只能写在一个源代码文件里,像如今只能写一个main方法一样。

  • 顶级语句中定义的本地函数和变量,在顶级代码段外部的任何地方调用他们都会产生错误。

下面这段代码就是一个比较好的示例:


using static System.Console;
using System.Threading.Tasks;

WriteLine("Hello,");
Print(args[0]);
await Task.Delay(1000);
return 0;

void Print(string arg)
{
 WriteLine(arg);
}

2.2 原理

我们知道,C#作为面向对象的编程语言,一切类型都是面向对象的,要有类型和成员定义。顶级语句表面看着好像违反了这一规则,实际上没有。这是因为,顶级语句最终还是在编译的时候,被作为全局命空间中Program类的Main方法体中一段代码一起自动生成。如下所示:


static class Program
{
 static async Task Main(string[] args)
 {
   // 顶级语句
 }
}

需要注意的是,这里的类名Program和方法名Main只是用来举例,其实在编译器生成的不是这个名字。我们可以通过查看IL代码确认这一点:

C#9.0新特性详解——顶级程序语句(Top-Level Programs)

根据在顶级语句中是否有异步操作和返回值的情况,生成的入口函数签名也是不同的。具体如下面表格所示:


存在返回值不存在返回值
存在异步async static Task<int> Main(string[] args)async static Task Main(string[] args)
不存在异步static int Main(string[] args)static void Main(string[] args)

例如上面代码,生成的入口函数<Main>$就如下代码所示:


static class Program
{
 async static Task<int> Main(string[] args)
 {
   WriteLine("Hello");
   Print(args[0]);
   await Task.Delay(1000);
   return 0;

void Print(string arg)
   {
     WriteLine(arg);
   }
 }
}

3 结束语

使用顶级语句能简化我们的编码工作,使代码看起来简洁清晰,对初学者也很友好,本质上也未改变C#的语言的原有的语法结构,任何语句都可以使用,没有产生额外的限制,从这些方面来说,是一个值得肯定的变化。

来源:https://www.cnblogs.com/markkang/p/14091908.html?utm_source=tuicool&utm_medium=referral

标签:C#,9.0,新特性,顶级程序语句,Top-Level,Programs
0
投稿

猜你喜欢

  • C# WinForm实现图片浏览器

    2022-04-12 23:28:00
  • C语言中下标与指针的转换以及指向指针的指针的例子

    2023-05-15 23:46:49
  • Android图片占用内存全面分析

    2023-02-20 01:05:38
  • 详解如何将JAVA程序制作成可以直接执行的exe文件

    2023-11-23 21:12:40
  • Android CardView详解及使用方法和实例

    2023-01-11 01:04:30
  • Android中ViewPager组件的基本用法及实现图片切换的示例

    2021-09-28 17:49:42
  • android studio 3.6.1导入项目报错提示无法下载classpath里的内容

    2021-09-28 11:02:57
  • Spring Security 构建rest服务实现rememberme 记住我功能

    2023-03-29 14:42:03
  • Java使用poi操作excel实例解析

    2022-01-26 00:15:41
  • RocketMQ生产者如何规避故障Broker方式详解

    2022-06-23 04:36:10
  • MyBatis-Plus逻辑删除和字段自动填充的实现

    2023-01-08 03:45:54
  • 详谈.net中的垃圾回收机制

    2022-12-04 03:52:27
  • SpringBoot实现文件上传与下载功能的示例代码

    2021-11-10 09:15:32
  • 一文详解Spring是怎么读取配置Xml文件的

    2023-07-30 00:27:37
  • Android应用程序保持后台唤醒(使用WakeLock实现)

    2022-07-03 07:46:13
  • java实战之桌球小游戏

    2022-04-22 20:40:13
  • Android之高德地图定位SDK集成及地图功能实现

    2023-12-06 07:33:16
  • 如何利用Spring MVC实现RESTful风格

    2021-06-06 02:02:13
  • 详解三种C#实现数组反转方式

    2023-10-09 20:29:23
  • macOS下Spring Boot开发环境搭建教程

    2023-11-05 15:50:59
  • asp之家 软件编程 m.aspxhome.com