C#9.0新特性之四:顶级程序语句(Top-Level Programs)
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代码确认这一点:
根据在顶级语句中是否有异步操作和返回值的情况,生成的入口函数签名也是不同的。具体如下面表格所示:
| 存在返回值 | 不存在返回值 | |
|---|---|---|
| 存在异步 | 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#的语言的原有的语法结构,任何语句都可以使用,没有产生额外的限制,从这些方面来说,是一个值得肯定的变化。
如对您有价值,请推荐,您的鼓励是我继续的动力,在此万分感谢。关注本人公众号“码客风云”,享第一时间阅读最新文章。

C#9.0新特性之四:顶级程序语句(Top-Level Programs)的更多相关文章
- C# 9.0 新特性预览 - 顶级语句
C# 9.0 新特性预览 - 顶级语句 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们 ...
- C# 9.0 新特性预览 - init-only 属性
C# 9.0 新特性预览 - init-only 属性 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章 ...
- 浅谈Tuple之C#4.0新特性那些事儿你还记得多少?
来源:微信公众号CodeL 今天给大家分享的内容基于前几天收到的一条留言信息,留言内容是这样的: 看了这位网友的留言相信有不少刚接触开发的童鞋们也会有同样的困惑,除了用新建类作为桥梁之外还有什么好的办 ...
- Java基础和JDK5.0新特性
Java基础 JDK5.0新特性 PS: JDK:Java Development KitsJRE: Java Runtime EvironmentJRE = JVM + ClassLibary JV ...
- Visual Studio 2015速递(1)——C#6.0新特性怎么用
系列文章 Visual Studio 2015速递(1)——C#6.0新特性怎么用 Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力) Visual Studi ...
- atitit.Servlet2.5 Servlet 3.0 新特性 jsp2.0 jsp2.1 jsp2.2新特性
atitit.Servlet2.5 Servlet 3.0 新特性 jsp2.0 jsp2.1 jsp2.2新特性 1.1. Servlet和JSP规范版本对应关系:1 1.2. Servlet2 ...
- 背水一战 Windows 10 (1) - C# 6.0 新特性
[源码下载] 背水一战 Windows 10 (1) - C# 6.0 新特性 作者:webabcd 介绍背水一战 Windows 10 之 C# 6.0 新特性 介绍 C# 6.0 的新特性 示例1 ...
- C# 7.0 新特性2: 本地方法
本文参考Roslyn项目中的Issue:#259. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...
- C# 7.0 新特性1: 基于Tuple的“多”返回值方法
本文基于Roslyn项目中的Issue:#347 展开讨论. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: ...
随机推荐
- 模板——Splay
$Splay$ #include <bits/stdc++.h> #define inf (int)1e9 using namespace std; const int N=1e5+100 ...
- vim编辑器使用简介
使用格式 vim [option] /path/to/somefile ... option: -o水平分割 -O垂直分割 +打开后在最后一行 +Num打开后在地Num行,加号与Num之间不能有空格 ...
- 通过Portwigge的Web安全漏洞训练平台,学习SSRF
前言 Portswigger是Burpsuite的官网,也是一个非常好的漏洞训练平台.其Web安全靶场地址为:https://portswigger.net/web-security/ 该靶场的训练内 ...
- JIRA、Confluence等产品明年2月停售本地化版本,将影响中国近90%的客户!
作为目前应用最为广泛的软件开发管理软件,JIRA.Confluence等产品几乎被所有的科技型公司所应用.我们的每天的任务管理.文档编写等工作几乎都在这些软件的帮助下进行和管理.当然我也不例外,在读书 ...
- 利用sklearn实现knn
基于上面一篇博客k-近邻利用sklearns实现knn #!/usr/bin/env python # coding: utf-8 # In[1]: import numpy as np import ...
- 创建Grafana监控视图
前言 Grafana允许查询,可视化,警报和了解指标,无论它们存储在哪里. 可视化:具有多种选项的快速灵活的客户端图.面板插件提供了许多不同的方式来可视化指标和日志. 动态仪表盘:使用模板变量创建动态 ...
- mysql之binlog和各类日志介绍
1.错误日志 错误日志作用: 记录MySQL的启动.停止信息以及在MySQL运行过程中的错误信息. 参数log_error(默认开启) 修改后重启生效 log_error=[path/[file_n ...
- Mon失效处理方法
假设环境为三个mon,主机名为mon1.mon2.mon3,现在mon3上面的系统盘损坏,mon的数据完全丢失,现在需要对mon3进行恢复处理 1.停止所有mon进程,可以不停其他进程,需要停止内核客 ...
- 微信_跳一跳辅助程序_Python_(带GitHub项目地址)
1.安装Python(推荐3.6) https://www.python.org/downloads/ 2.在github上下载脚本 [github项目地址](https://github.com/w ...
- Environment Cubemap
要创建一个Cubemap(将您的环境捕获到一个Cubemap中),您需要去Unity Documentation复制RenderCubemapWizard.cs脚本! 然后在"Project ...