前面咱們分別介紹了一些 C# 9 中的新特性,還有一些我以爲須要瞭解一下的新特性,寫一篇做爲補充。git
在以往的代碼裏,一個應用程序必需要有 Main
方法才能運行,從 C# 9 開始,支持沒有 Main
方法的程序,實際編譯以後仍是會有一個 Main
方法的,使用示例以下:github
using static System.Console; WriteLine("Hello World!");
實際編譯出來的結果以下:express
實際會生成一個沒有命名空間的 <Program>$
的類型,類中定義的有一個名稱是 <Main>$
的靜態方法安全
從 C# 7.2 開始,咱們可使用 _
來表明一個不使用的變量,廢棄變量,可是在 lambda 表達式裏默認不能有同名的參數名,從 C# 9 開始,支持多個參數同時使用 _
來表示,以下所示:less
Func<int, int, int> constant = (_, _) => 42;
從 C# 9 開始,咱們能夠在局部方法(本地方法)上設置 Attributeide
public static void MainTest() { InnerTest(); [MethodImpl(MethodImplOptions.Synchronized)] void InnerTest() { Console.WriteLine(nameof(InnerTest)); } }
在 C# 2.0 以後就支持了分部類,一般分部類會出如今動態代碼生成的地方,對於想要將一個類型拆分到多個文件裏,咱們一般也會考慮用到分部類。性能
C# 3.0 開始支持了分部方法,可是功能比較弱,使用起來有一些限制:spa
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 分部方法規則的容許沒有方法體,不然必需要有方法體code
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
來看反編譯的代碼,能夠看到有一個 Module
的類,在這個 Module
類的靜態構造方法裏會去調用聲明爲 ModuleInitializer
的方法
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; }
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` } }
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(); } }
除此以外還有一些小的更新特性,詳細能夠參考文末給出的官方文檔。