C# 9 新特性 —— 补充篇

Intro

前面我们分别介绍了一些 C# 9 中的新特性,还有一些我觉得需要了解一下的新特性,写一篇作为补充。

Top-Level Statements

在以往的代码里,一个应用程序必须要有 Main 方法才能运行,从 C# 9 开始,支持没有 Main 方法的程序,实际编译之后还是会有一个 Main 方法的,使用示例如下:

using static System.Console;

WriteLine("Hello World!");

实际编译出来的结果如下:

实际会生成一个没有命名空间的 <Program>$ 的类型,类中定义的有一个名称是 <Main>$ 的静态方法

Improved discards in lambda input parameter

从 C# 7.2 开始,我们可以使用 _ 来代表一个不使用的变量,废弃变量,但是在 lambda 表达式里默认不能有同名的参数名,从 C# 9 开始,支持多个参数同时使用 _ 来表示,如下所示:

Func<int, int, int> constant = (_, _) => 42;

Attributes for local function

从 C# 9 开始,我们可以在局部方法(本地方法)上设置 Attribute

public static void MainTest()
{
InnerTest(); [MethodImpl(MethodImplOptions.Synchronized)]
void InnerTest()
{
Console.WriteLine(nameof(InnerTest));
}
}

Partition methods

在 C# 2.0 之后就支持了分部类,通常分部类会出现在动态代码生成的地方,对于想要将一个类型拆分到多个文件里,我们通常也会考虑用到分部类。

C# 3.0 开始支持了分部方法,但是功能比较弱,使用起来有一些限制:

  • 分部类型各部分中的签名必须匹配。
  • 方法必须返回 void。
  • 不允许使用访问修饰符。 分部方法是隐式 private 的。

C# 9 增强了分部方法的支持,分部方法的使用,只能在一个地方有方法体,目前主要是为了 Source Generator 引入了这个语言特性,可以在一个地方定义方法,在另外一个地方实现方法体,示例如下:

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");
}
}

符合 C# 3.0 分部方法规则的允许没有方法体,否则必须要有方法体

ModuleInitializer

Source Generator 除了上面的分部方法之外,还引入了一个 ModuleInitializer 的概念,就像它的名字,模块初始化器,当用到某个模块的时候就会调用对应的 ModuleInitializer 方法进行初始化操作

ModuleInitializer 定义如下:

namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class ModuleInitializerAttribute : Attribute
{
}
}

使用示例如下:

internal static class ModuleInitializerSample
{
/// <summary>
/// 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
/// </summary>
[ModuleInitializer]
public static void Initialize()
{
Console.WriteLine($"{nameof(ModuleInitializerAttribute)} works");
}
}

ModuleInitlializer 对应的方法有几个要求

  • 必须是静态方法
  • 不能有方法参数,无参数方法
  • 方法没有返回值,返回类型必须是 void
  • 不能是泛型方法
  • 不能在泛型类中
  • 必须能够被所在模块访问的到(至少是 internal)



来看反编译的代码,可以看到有一个 Module 的类,在这个 Module 类的静态方法里会去调用声明为 ModuleInitializer 的方法

Function Pointer

C# 9 支持方法指针,对委托进一步的”C++化“,进一步提升性能,属于非安全代码,使用需开启 unsafe,使用示例如下:

public static unsafe void MainTest()
{
delegate*<int, int, int> pointer = &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;
}

Static Anoymouse Method

C# 9 开始支持在匿名方法或者表达式前声明 static,声明 static 之后就不能使用实例变量,只能使用静态变量,如下所示:

internal class StaticAnonymousMethod
{
private readonly int num = 1; public void MainTest()
{
// anonymous method
Action action = () => { Console.WriteLine(num); };
Action action1 = static () => { };// can not access `num` //expression
Expression<Func<int, bool>> expression = i => i > num;
Expression<Func<int, bool>> expression1 = static i => i > 1;// can not access `num`
}
}

Covariant Return Type

C# 9 开始支持返回类型的 Covariant(协变), 对于 override 方法可返回从重写基方法的返回类型派生的类型。 这对于record和其他支持工厂方法的类型会很有用。可以参考下面的使用示例:

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();
}
}

More

除此之外还有一些小的更新特性,详细可以参考文末给出的官方文档。

Reference

C# 9 新特性 —— 补充篇的更多相关文章

  1. iOS开发——新特性OC篇&IOS9 SDK新特性

    iOS9 SDK新特性 WWDC 2015苹果开发者大会是移动开发者一年一度的盛会,InfoQ中文站除了第一时间整理Keynote内容分享给大家之外,还邀请了资深的一线开发者分享他们的收获.本文为王巍 ...

  2. iOS开发——新特性OC篇&Swift 2.0新特性

    Swift 2.0新特性     转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度 ...

  3. iOS开发——新特性OC篇&IOS9 系统新特性

    IOS9 系统新特性 2015年6月89号凌晨召开的WWDC 2015苹果开发者大会发布了全新的iOS 9系统,PC6小编今天给大家整理了这次iOS9的系统更新带来了哪些新的功能与升级,本次新功能一览 ...

  4. iOS开发——新特性OC篇&Objective新特性

    Objective新特性 Overview 自 WWDC 2015 推出和开源 Swift 2.0 后,大家对 Swift 的热情又一次高涨起来,在羡慕创业公司的朋友们大谈 Swift 新特性的同时, ...

  5. JDK8之新特性扩展篇

    之前分篇章讲了一些JKD8中添加的新特性,还有一些新特性这里也一并讲下. BASE64 base64编码解码已经被加入到了jdk8中了. import java.nio.charset.Standar ...

  6. iOS开发——新特性Swift篇&Swift 2.0 异常处理

    Swift 2.0 异常处理 WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法.这篇文章会主要围绕这个方面进行讨论. 如何建造异常类型? 在 i ...

  7. 总结CSS3新特性(颜色篇)

    颜色: CSS3新增加了hsl(), hsla(), rgb(),rgba()四个函数来创建color值; hsl(): hsl函数:h(色调),s(饱和度),l(亮度); 色调:为0-360之间的数 ...

  8. 总结CSS3新特性(Transform篇)

    概述: CSS3新添加的Transform可以改变元素在可视化区域的坐标(这种改变不会引起文档的重排,只有重排),以及形状,还有些3D形变.结合 Animation(这里以后会有个链接的) 能实现酷炫 ...

  9. 总结CSS3新特性(Animation篇)

    动画(Animation),是CSS3的亮点.//之一 通过animation属性指定@keyframe来完成关键帧动画; @keyframe用法: @keyframes name { 0% { to ...

随机推荐

  1. PyQt(Python+Qt)学习随笔:自定义信号在emit发射信号时报错:AttributeError: object has no attribute

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 如果使用自定义信号,一定要记得信号是类变量,必须在类中定义,不能在实例 ...

  2. 第8.24节 使用__subclasses__查看类的直接子类

    在<第8.9节 Python类中内置的__bases__属性>中介绍了__bases__这个类的特殊变量可以查看类的直接父类,而__subclasses__() 方法的使用则与__base ...

  3. PyQt(Python+Qt)学习随笔:视图中类QAbstractItemView的dragDropOverwriteMode属性

    老猿Python博文目录 老猿Python博客地址 一.属性的作用 dragDropOverwriteMode属性用于控制视图的拖放行为,如果其值为True,则视图中选定的数据将在拖拽数据放下时被覆盖 ...

  4. 74CMS3.0储存型XSS漏洞代码审计

    发现一个总结了乌云以前代码审计案例的宝藏网站:https://php.mengsec.com/ 希望自己能成为那个认真复现和学习前辈们思路的那个人,然后准备慢慢开始审计一些新的小型cms了 骑士cms ...

  5. [BJDCTF 2nd]简单注入

    [BJDCTF 2nd]简单注入 hint.txt出现了内容. 大概意思和国赛一道题相同. username处注入\来转义单引号,password处使用sql语句整数型注入. 例如: 传入admin\ ...

  6. AcWing 406. 放置机器人

    大型补档计划 题目链接 预处理每个列.行连续块. 每个每个列行只能在一个位置匹配,否则冲突. 符合二分图性质,跑匈牙利即可. 点数最坏情况 \(N * M\) (墙空地相间分布),边数最坏情况 \(N ...

  7. 题解-CF1140E Palindrome-less Arrays

    CF1140E Palindrome-less Arrays \(n\) 和 \(k\) 和 \(n\) 个数的序列 \(a\).把 \(a\) 中的 \(-1\) 替换成 \([1,k]\) 之间的 ...

  8. 磁盘inode节点被占满的解决方法

    问题: Linux服务器,查看日志发现程序无法继续写文件,但是用df -h查看磁盘容量还有剩余. 排查思路:怀疑是机器的inode节点被占满,使用df -i查看磁盘inode节点使用情况,果然是ino ...

  9. [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用

    [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用 目录 [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用 0x00 摘要 0x01 业务领域 1.1 应用场景 0x02 定 ...

  10. ES6新增数据类型Symbol

    Symbol的含义? ES6(2015) 引入了第七种原始数据类型Symbol,Symbol英文文意思为 符号.象征.标记.记号,在 js 中更确切的翻译应该为独一无二的 Symbol的使用? Sym ...