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#的语言的原有的语法结构,任何语句都可以使用,没有产生额外的限制,从这些方面来说,是一个值得肯定的变化。
如对您有价值,请推荐,您的鼓励是我继续的动力,在此万分感谢。关注本人公众号“码客风云”,享第一时间阅读最新文章。
最新文章
- SOAPUI使用教程-REST源和方法
- <;十四>;JDBC_c3p0数据库连接池
- javascript 常见方法记录
- get([index])
- install vim
- Xcode离线安装帮助文档
- HTML插入Flash的全兼容完美解决方案-SWFObject
- Eclipse的maven构建一个web项目,以构建SpringMVC项目为例
- eclipse关联源码 Failed to create the part&#39;s controls
- C#正则怎么判断字符串中是否有汉字
- ios NSString 去除空格和回车
- css组件规范
- 【IE6的疯狂之十】父级使用padding后子元素绝对定位的BUG
- .net 利用Emit将object转为DbParameter,DataTable转为List<;>;
- [DeeplearningAI笔记]改善深层神经网络_深度学习的实用层面1.9_归一化normalization
- [BZOJ3110] [Zjoi2013] K大数查询 (树套树)
- 2018上C语言程序设计(高级)- 第0次作业成绩
- 位图(BitMap)
- react,react native,webpack,ES6,node.js----------今天上午学了一下node.js
- SpaceSyntax【空间句法】之DepthMapX学习:唠叨(目录)
热门文章
- MapReduce在Shuffle阶段按Mapper输出的Value进行排序
- 第一行代码中RecyclerView添加依赖库问题
- leetcode104:permutations
- 最全总结 | 聊聊 Python 办公自动化之 Excel(下)
- centos 7.6 虚拟机开启网卡
- 利用requestes\pyquery\BeautifulSoup爬取某租房公寓(深圳市)4755条租房信息及总结
- git设置个人信息
- JS处理Long类型精度丢失问题
- html页面转PDF、图片操作记录
- 又陷入知识盲区了,面试被问SpringBoot集成dubbo,我当时就懵了