C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

栏目: IT技术 · 发布时间: 4年前

内容简介:.NET 5 终于在 6月25日 发布了第六个预览版,随之而来的是更多的新特性加入到了 C# 9 Preview 中,这个系列也可以继续往下写了,废话不多说,今天来看一下下载最新的

一:背景

1. 讲故事

.NET 5 终于在 6月25日 发布了第六个预览版,随之而来的是更多的新特性加入到了 C# 9 Preview 中,这个系列也可以继续往下写了,废话不多说,今天来看一下 Top-level programsExtending Partial Methods 两大新特性。

2. 安装必备

下载最新的 .net 5 preview 6

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

下载最新的 Visual Studio 2019 version 16.7 Preview 3.1

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

二:新特性研究

1. Top-level programs

如果大家玩过 python,应该知道在 xxx.py 中写一句 print,这程序就能跑起来了,简单高效又粗暴,很开心的是这特性被带到了C# 9.0 中。

  • 修改前
using System;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
  • 修改后
System.Console.WriteLine("Hello World!");

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

这就有意思了,Main入口函数去哪了? 没它的话,JIT还怎么编译代码呢? 想知道答案的话用 ILSpy 反编译看一下就好啦!

.class private auto ansi abstract sealed beforefieldinit $Program
    extends [System.Runtime]System.Object
{
    .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    // Methods
    .method private hidebysig static 
        void $Main (
            string[] args
        ) cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 18 (0x12)
        .maxstack 8
        .entrypoint

        IL_0000: ldstr "Hello World!"
        IL_0005: call void [System.Console]System.Console::WriteLine(string)
        IL_000a: nop
        IL_000b: call string [System.Console]System.Console::ReadLine()
        IL_0010: pop
        IL_0011: ret
    } // end of method $Program::$Main

} // end of class $Program

从 IL 上看,类变成了 $Program , 入口方法变成了 $Main , 这就好玩了,在我们的印象中入口函数必须是 Main ,否则编译器会给你一个大大的错误,你加了一个 $ 符号,那CLR还能认识吗? 能不能认识我们用 windbg 看一些托管和非托管堆栈,看看有什么新发现。

0:010> ~0s
ntdll!NtReadFile+0x14:
00007ffe`f8f8aa64 c3              ret
0:000> !dumpstack
OS Thread Id: 0x7278 (0)
Current frame: ntdll!NtReadFile + 0x14
Child-SP         RetAddr          Caller, Callee
0000008551F7E810 00007ffed1e841dc (MethodDesc 00007ffe4020d500 + 0x1c System.Console.ReadLine()), calling 00007ffe400ab090
0000008551F7E840 00007ffe4014244a (MethodDesc 00007ffe401e58f0 + 0x3a $Program.$Main(System.String[])), calling 00007ffe40240f58
0000008551F7E880 00007ffe9fcc8b43 coreclr!CallDescrWorkerInternal + 0x83 [F:\workspace\_work\1\s\src\coreclr\src\vm\amd64\CallDescrWorkerAMD64.asm:101]
0000008551F7E8C0 00007ffe9fbd1e03 coreclr!MethodDescCallSite::CallTargetWorker + 0x263 [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:554], calling coreclr!CallDescrWorkerWithHandler [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:56]
0000008551F7E950 00007ffe9fb8c4e5 coreclr!MethodDesc::IsVoid + 0x21 [F:\workspace\_work\1\s\src\coreclr\src\vm\method.cpp:1098], calling coreclr!MetaSig::IsReturnTypeVoid [F:\workspace\_work\1\s\src\coreclr\src\vm\siginfo.cpp:5189]
0000008551F7EA00 00007ffe9fb8c4bf coreclr!RunMainInternal + 0x11f [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1488], calling coreclr!MethodDescCallSite::CallTargetWorker [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:266]
0000008551F7EB30 00007ffe9fb8c30a coreclr!RunMain + 0xd2 [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1559], calling coreclr!RunMainInternal [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1459]

从上面堆栈的流程图看: coreclr!RunMain -> coreclr!MethodDesc -> coreclr!CallDescrWorkerInternal -> $Program.$Main , 确实被调用了,不过有一个重大发现,在 $Program.$Main 调用之前底层的 CLR 读取了 方法描述符,这就是一个重大突破点,方法描述符在哪里呢? 可以用 ildasm 去看一下元数据列表。

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

可以看到,入口函数那里打上了一个 ENTRYPOINT 标记,这就说明入口函数名其实是可以随便更改的,只要被 ENTRYPOINT 打上标记即可,CoreCLR就能认的出来~~~

2. Partial Methods

我们知道 部分方法 是一个很好的桩函数,而且在 C# 3.0 中就已经实现了,那时候给我们增加了很多限制,如下图:

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

翻译过来就是:

  • 部分方法的签名必须一致
  • 方法必须返回void
  • 不允许使用访问修饰符,而且还是隐式私有的。

在 C# 9.0 中放开了对 方法签名 的所有限制,正如 issue 总结:

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

这是一个非常好的消息,现在你的部分方法上可以加上各种类型的返回值啦,这里我举一个例子:

class Program
    {
        static void Main(string[] args)
        {
            var person = new Person();

            Console.WriteLine(person.Run("jack"));
        }
    }

    public partial class Person
    {
        public partial string Run(string name);
    }

    public partial class Person
    {
        public partial string Run(string name) => $"{name}:开溜了~";
    }

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

然后我们用 ILSpy 简单看看底层怎么玩的,如下图可以看到其实就是一个简单的合成,对吧。

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

现在我有想法了,如果我不给 Run 方法实现会怎么样? 把下面的 partial 类注释掉看一下。

C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

从报错信息看,可访问的修饰符必须要有方法实现,<font color="red">还以为直接编译的时候抹掉呢。</font> 这就起不到桩函数的作用:-D,不过这个特性还是给了我们更多的可能用的到的应用场景吧。

三:总结

本篇两个特性还是非常实用的,Top-level programs 让我们可以写更少的代码,甚至拿起 记事本 都可以快捷的编写类似一次性使用的测试代码, Partial Methods 特性留给大家补充吧,我基本上算是没用过 (┬_┬)。


以上所述就是小编给大家介绍的《C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

人人都是产品经理

人人都是产品经理

苏杰 / 电子工业出版社 / 2010年4月 / 45.00元

这是写给“-1到3岁的产品经理”的书,适合刚入门的产品经理、产品规划师、需求分析师,以及对做产品感兴趣的学生,用户体验、市场运营、技术部门的朋友们,特别是互联网、软件行业。作为一名“4岁的产品经理”,作者讲述了过去3年的经历与体会,与前辈们的书不同,本书就像你走到作者身边,说“嗨哥们!晚上有空吃个饭么,随便聊聊做产品的事吧”,然后作者说“好啊”。 书名叫“人人都是产品经理”,是因为作者觉得过......一起来看看 《人人都是产品经理》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

html转js在线工具
html转js在线工具

html转js在线工具