C# 9 新特性 —— 补充篇
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
- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9
- https://github.com/WeihanLi/SamplesInPractice/tree/master/CSharp9Sample
C# 9 新特性 —— 补充篇的更多相关文章
- iOS开发——新特性OC篇&IOS9 SDK新特性
iOS9 SDK新特性 WWDC 2015苹果开发者大会是移动开发者一年一度的盛会,InfoQ中文站除了第一时间整理Keynote内容分享给大家之外,还邀请了资深的一线开发者分享他们的收获.本文为王巍 ...
- iOS开发——新特性OC篇&Swift 2.0新特性
Swift 2.0新特性 转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度 ...
- iOS开发——新特性OC篇&IOS9 系统新特性
IOS9 系统新特性 2015年6月89号凌晨召开的WWDC 2015苹果开发者大会发布了全新的iOS 9系统,PC6小编今天给大家整理了这次iOS9的系统更新带来了哪些新的功能与升级,本次新功能一览 ...
- iOS开发——新特性OC篇&Objective新特性
Objective新特性 Overview 自 WWDC 2015 推出和开源 Swift 2.0 后,大家对 Swift 的热情又一次高涨起来,在羡慕创业公司的朋友们大谈 Swift 新特性的同时, ...
- JDK8之新特性扩展篇
之前分篇章讲了一些JKD8中添加的新特性,还有一些新特性这里也一并讲下. BASE64 base64编码解码已经被加入到了jdk8中了. import java.nio.charset.Standar ...
- iOS开发——新特性Swift篇&Swift 2.0 异常处理
Swift 2.0 异常处理 WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法.这篇文章会主要围绕这个方面进行讨论. 如何建造异常类型? 在 i ...
- 总结CSS3新特性(颜色篇)
颜色: CSS3新增加了hsl(), hsla(), rgb(),rgba()四个函数来创建color值; hsl(): hsl函数:h(色调),s(饱和度),l(亮度); 色调:为0-360之间的数 ...
- 总结CSS3新特性(Transform篇)
概述: CSS3新添加的Transform可以改变元素在可视化区域的坐标(这种改变不会引起文档的重排,只有重排),以及形状,还有些3D形变.结合 Animation(这里以后会有个链接的) 能实现酷炫 ...
- 总结CSS3新特性(Animation篇)
动画(Animation),是CSS3的亮点.//之一 通过animation属性指定@keyframe来完成关键帧动画; @keyframe用法: @keyframes name { 0% { to ...
随机推荐
- PyQt(Python+Qt)学习随笔:QDial刻度盘部件功能简介
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 Designer中的Dial刻度盘输入部 ...
- pandas LabelEncoder方法,对离散值进行编码,并储存
# 3.离散值进行LabelEncoder #处理数据的三个步骤,去重,处理缺失值,离散值LabelEncoder from sklearn import preprocessingfrom skle ...
- Jenkins Job间传递参数的一种方法
场景: Jenkins 中可以建多个Job,一般是主编译Job,多个子Job. 子Job要用主Job中的版本号,编译号. 1) 在主Job里面添加脚本命令: echo set MainVersion ...
- Scrum 冲刺 第三篇
Scrum 冲刺 第三篇 每日会议照片 昨天已完成工作 队员 昨日完成任务 黄梓浩 继续完成app项目架构搭建 黄清山 完成部分个人界面模块数据库的接口 邓富荣 完成部分后台首页模块数据库的接口 钟俊 ...
- 手写线程池,对照学习ThreadPoolExecutor线程池实现原理!
作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...
- 题解-CF617E XOR and Favorite Number
题面 CF617E XOR and Favorite Number 给定 \(n,m,k\) 和 \(n\) 个数的序列 \(a_i\),\(m\) 次求区间 \([l,r]\) 中异或值为 \(k\ ...
- MVCAdmin项目知识点记录
1.在过滤器中,用ViewBag类似的东西,要((ViewResult)filterContext.Result).ViewBag. 2.Controller中自己定义的非Action方法中(包括构造 ...
- CSS3全览_文本+视觉+盒子+背景颜色
CSS全览_文本+视觉+盒子+背景颜色 目录 CSS全览_文本+视觉+盒子+背景颜色 1. 文本属性 2. 视觉格式化基础 3. 内边距, 边框, 轮廓和外边距 4. 颜色, 背景和渐变 作者: ht ...
- Clickhouse 在大数据分析平台 - 留存分析上的应用
导语 | 本文实践了对于千万级别的用户,操作总数达万级别,每日几十亿操作流水的留存分析工具秒级别查询的数据构建方案.同时,除了留存分析,对于用户群分析,事件分析等也可以尝试用此方案来解决. 文章作者: ...
- Java带Body内容的Http请求
使用Java进行Http请求: package test2; import com.mashape.unirest.http.HttpResponse; import com.mashape.unir ...