猪头四 發表於 2021-1-6 23:47:00

C# 9 新特性 —— 补充篇

<h1 id="c-9-新特性--补充篇">C# 9 新特性 —— 补充篇</h1>
<h2 id="intro">Intro</h2>
<p>前面我们分别介绍了一些 C# 9 中的新特性,还有一些我觉得需要了解一下的新特性,写一篇作为补充。</p>
<h2 id="top-level-statements">Top-Level Statements</h2>
<p>在以往的代码里,一个应用程序必须要有 <code>Main</code> 方法才能运行,从 C# 9 开始,支持没有 <code>Main</code> 方法的程序,实际编译之后还是会有一个 <code>Main</code> 方法的,使用示例如下:</p>
<pre><code class="language-csharp">using static System.Console;

WriteLine("Hello World!");
</code></pre>
<p>实际编译出来的结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/489462/202101/489462-20210106233638987-1722288603.png" alt="" loading="lazy"></p>
<p>实际会生成一个没有命名空间的 <code>&lt;Program&gt;$</code> 的类型,类中定义的有一个名称是 <code>&lt;Main&gt;$</code> 的静态方法</p>
<h2 id="improved-discards-in-lambda-input-parameter">Improved discards in lambda input parameter</h2>
<p>从 C# 7.2 开始,我们可以使用 <code>_</code> 来代表一个不使用的变量,废弃变量,但是在 lambda 表达式里默认不能有同名的参数名,从 C# 9 开始,支持多个参数同时使用 <code>_</code> 来表示,如下所示:</p>
<pre><code class="language-csharp">Func&lt;int, int, int&gt; constant = (_, _) =&gt; 42;
</code></pre>
<h2 id="attributes-for-local-function">Attributes for local function</h2>
<p>从 C# 9 开始,我们可以在局部方法(本地方法)上设置 Attribute</p>
<pre><code class="language-csharp">public static void MainTest()
{
    InnerTest();

   
    void InnerTest()
    {
      Console.WriteLine(nameof(InnerTest));
    }
}
</code></pre>
<h2 id="partition-methods">Partition methods</h2>
<p>在 C# 2.0 之后就支持了分部类,通常分部类会出现在动态代码生成的地方,对于想要将一个类型拆分到多个文件里,我们通常也会考虑用到分部类。</p>
<p>C# 3.0 开始支持了分部方法,但是功能比较弱,使用起来有一些限制:</p>
<ul>
<li>分部类型各部分中的签名必须匹配。</li>
<li>方法必须返回 void。</li>
<li>不允许使用访问修饰符。 分部方法是隐式 <code>private</code> 的。</li>
</ul>
<p>C# 9 增强了分部方法的支持,分部方法的使用,只能在一个地方有方法体,目前主要是为了 Source Generator 引入了这个语言特性,可以在一个地方定义方法,在另外一个地方实现方法体,示例如下:</p>
<pre><code class="language-csharp">partial class PartialMethod
{
    public static partial void MainTest();

    static partial void Test1();
}

partial class PartialMethod
{
    public static partial void MainTest()
    {
      Test1();
      Console.WriteLine("Partial method works");
    }
}
</code></pre>
<p>符合 C# 3.0 分部方法规则的允许没有方法体,否则必须要有方法体</p>
<h2 id="moduleinitializer"><code>ModuleInitializer</code></h2>
<p><code>Source Generator</code> 除了上面的分部方法之外,还引入了一个 <code>ModuleInitializer</code> 的概念,就像它的名字,模块初始化器,当用到某个模块的时候就会调用对应的 <code>ModuleInitializer</code> 方法进行初始化操作</p>
<p><code>ModuleInitializer</code> 定义如下:</p>
<pre><code class="language-csharp">namespace System.Runtime.CompilerServices
{

public sealed class ModuleInitializerAttribute : Attribute
{
}
}
</code></pre>
<p>使用示例如下:</p>
<pre><code class="language-csharp">internal static class ModuleInitializerSample
{
    /// &lt;summary&gt;
    /// Initializer for specific module
    ///
    /// Must be static
    /// Must be parameter-less
    /// Must return void
    /// Must not be a generic method
    /// Must not be contained in a generic class
    /// Must be accessible from the containing module
    /// &lt;/summary&gt;
   
    public static void Initialize()
    {
      Console.WriteLine($"{nameof(ModuleInitializerAttribute)} works");
    }
}
</code></pre>
<p><code>ModuleInitlializer</code> 对应的方法有几个要求</p>
<ul>
<li>必须是静态方法</li>
<li>不能有方法参数,无参数方法</li>
<li>方法没有返回值,返回类型必须是 <code>void</code></li>
<li>不能是泛型方法</li>
<li>不能在泛型类中</li>
<li>必须能够被所在模块访问的到(至少是 internal)</li>
</ul>
<p><img src="https://img2020.cnblogs.com/blog/489462/202101/489462-20210106234156030-419932456.png" alt="" loading="lazy"><br>
<img src="https://img2020.cnblogs.com/blog/489462/202101/489462-20210106234209040-1957973110.png" alt="" loading="lazy"></p>
<p>来看反编译的代码,可以看到有一个 <code>Module</code> 的类,在这个 <code>Module</code> 类的静态构造方法里会去调用声明为 <code>ModuleInitializer</code> 的方法</p>
<p><img src="https://img2020.cnblogs.com/blog/489462/202101/489462-20210106234356098-1120644185.png" alt="" loading="lazy"></p>
<h2 id="function-pointer">Function Pointer</h2>
<p>C# 9 支持方法指针,对委托进一步的”C++化“,进一步提升性能,属于非安全代码,使用需开启 <code>unsafe</code>,使用示例如下:</p>
<pre><code class="language-csharp">public static unsafe void MainTest()
{
    delegate*&lt;int, int, int&gt; pointer = &amp;Test;
    var result = pointer(1, 1);
    Console.WriteLine(result);
}

private static int Test(int num1, int num2)
{
    Console.WriteLine($"Invoke in {nameof(Test)}, {num1}_{num2}");
    return num1 + num2;
}
</code></pre>
<h2 id="static-anoymouse-method">Static Anoymouse Method</h2>
<p>C# 9 开始支持在匿名方法或者表达式前声明 <code>static</code>,声明 <code>static</code> 之后就不能使用实例变量,只能使用静态变量,如下所示:</p>
<pre><code class="language-csharp">internal class StaticAnonymousMethod
{
    private readonly int num = 1;

    public void MainTest()
    {
      // anonymous method
      Action action = () =&gt; { Console.WriteLine(num); };
      Action action1 = static () =&gt; { };// can not access `num`

      //expression
      Expression&lt;Func&lt;int, bool&gt;&gt; expression = i =&gt; i &gt; num;
      Expression&lt;Func&lt;int, bool&gt;&gt; expression1 = static i =&gt; i &gt; 1;// can not access `num`
    }
}
</code></pre>
<h2 id="covariant-return-type">Covariant Return Type</h2>
<p>C# 9 开始支持返回类型的 <code>Covariant</code>(协变), 对于 <code>override</code> 方法可返回从重写基方法的返回类型派生的类型。 这对于<code>record</code>和其他支持工厂方法的类型会很有用。可以参考下面的使用示例:</p>
<pre><code class="language-csharp">internal class CovariantReturnType
{
    private abstract class Operation
    {
    }

    private abstract class OperationFactory
    {
      public abstract Operation GetOperation();
    }

    private class AddOperation : Operation
    {
    }

    private class AddOperationFactory : OperationFactory
    {
      // 返回类型协变,返回具体的类型而不是抽象类中声明的类型
      public override AddOperation GetOperation()
      {
            return new();
      }
    }

    public static void MainTest()
    {
      var factory = new AddOperationFactory();
      factory.GetOperation();
    }
}
</code></pre>
<h2 id="more">More</h2>
<p>除此之外还有一些小的更新特性,详细可以参考文末给出的官方文档。</p>
<h2 id="reference">Reference</h2>
<ul>
<li>https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9</li>
<li>https://github.com/WeihanLi/SamplesInPractice/tree/master/CSharp9Sample</li>
</ul>


</div>
<div id="MySignature" role="contentinfo">
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。<br><br>
来源:https://www.cnblogs.com/weihanli/p/14244158.html
頁: [1]
查看完整版本: C# 9 新特性 —— 补充篇