C ා 9.0 finally comes, top level programs and Partial Methods two new features explore

1: Background

1. Story telling

. NET 5 finally released the sixth preview version on June 25, with more new features added to the C ා 9 preview. This series can also continue to write. There is no more nonsense. Today, let's take a look at the top level programs and Extending Partial Methods.

2. Necessary for installation

Download the latest. net 5 preview 6.

Download the latest Visual Studio 2019 version 16.7 Preview 3.1

2: Research on new characteristics

1. Top-level programs

If you've played python, you should know xxx.py Write a print in, and the program will run. It's simple, efficient and rough. It's very happy that this feature has been brought to C × 9.0.

  • Before modification

using System;

namespace ConsoleApp2
    class Program
        static void Main(string[] args)
            Console.WriteLine("Hello World!");
  • After modification

System.Console.WriteLine("Hello World!");

That's interesting. Where is the Main entry function? Without it, how can JIT compile code? If you want to know the answer, just decompile it with 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

        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

From the perspective of IL, the class becomes $Program, and the entry method becomes $Main, which is fun. In our impression, the entry function must be Main, or the compiler will give you a big error. If you add a $symbol, can CLR recognize it? Can you know that we use windbg to look at some managed and unmanaged stacks and see what we have found.

0:010> ~0s
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]

From the flow chart of the above stack, it can be seen that: coreclr! Runmain - > coreclr! MethodDesc - > coreclr! Calldescrworkerinternal - > Program.$Main is indeed called, but there is a major discovery that the underlying CLR read the method descriptor before the call of $Program.$Main. This is a major breakthrough. Where is the method descriptor? You can use ildasm to look at the metadata list.

As you can see, the entry function is marked with an ENTRYPOINT, which means that the entry function name can be changed at will. As long as it is marked with ENTRYPOINT, CoreCLR can recognize it~~~

2. Partial Methods

We know that part of the method is a good pile function, and it has been implemented in C ා 3.0. At that time, we added many restrictions, as shown in the following figure:

The translation is:

  • Signature of some methods must be consistent
  • Method must return void
  • Access modifiers are not allowed and are implicitly private.

In C ා 9.0, all restrictions on method signature are released, as the issue concludes:

This is very good news. Now you can add various types of return values to some of your methods. Here is an example:

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


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

    public partial class Person
        public partial string Run(string name) => $"{name}:It's off~";

Then we can use ILSpy to see how to play the bottom layer. As shown in the figure below, it is actually a simple synthesis, right.

Now I have an idea. What if I don't give the Run method implementation? Note out the partial class below.

From the error information, the accessible modifiers must be implemented in a way, < font color = "red" > thought they would be erased when compiling directly. < / font > this doesn't work as a pile function: - D, but this feature still gives us more possible application scenarios.

3: Summary

The two features of this article are very practical. Top level programs allow us to write less code. Even if we pick up Notepad, we can quickly write test code similar to one-time use. Let's add the Partial Methods feature. I haven't used it (┬).

Tags: C# Python less

Posted on Sat, 27 Jun 2020 01:02:58 -0400 by mmitdnn