⚡ C# 9 小特性速查

Top-level Statements · Pattern Matching 增强 · Target-typed new · Covariant Returns · 📖 完整课程

顶级语句Top-level Statements

C# 8 及之前

using System;
namespace App {
  class Program {
    static void Main(string[] a) {
      Console.WriteLine("Hi");
    }
  }
}

C# 9

Console.WriteLine("Hi");
能力支持?
using 导入✅ 文件开头
await 异步✅ 自动生成 async Task Main
访问 args✅ 隐式可用
return exit code
定义类/方法(放语句后)
一个项目多个文件用❌ 只能一个文件
编译器把顶级语句合成为 internal class Program { static void $Main(string[] args) { ... } }。需要暴露 Program 给集成测试?另建文件写 public partial class Program { }——自动合并。

模式组合器Pattern Combinators (C# 9)

关键字含义写法示例
not反转模式x is not nullx is not 0
and同时满足(交集)x is > 0 and < 100
or满足其一(并集)ch is 'a' or 'e' or 'i' or 'o' or 'u'
优先级:not > and > or(和 ! > && > || 一致)。不能用括号分组模式——复杂场景用 when 代替。
is not null!= null。前者是模式匹配——不走 operator != 重载,更安全。C# 9+ 推荐作为首选的 null 检查写法。

关系模式Relational Patterns (C# 9)

// 直接写比较——不再需要 when
return score switch
{
    >= 90 => "A",
    >= 80 => "B",
    >= 60 => "C",
    < 60 => "F",
};

// 关系模式 + 属性模式
return order switch
{
    { IsVip: true, Total: >= 1000 } => 0.20m,
    { IsVip: true }                   => 0.10m,
    { Total: >= 500 }                   => 0.05m,
    _                                   => 0m,
};
关系模式只能比较常量/字面量,不能调用方法。涉及方法调用(StartsWith)或跨变量比较(w == h)仍用 when

目标类型 newTarget-typed new

场景C# 8C# 9
局部变量List<string> x = new List<string>();List<string> x = new();
字段初始化private List<int> _nums = new List<int>();private List<int> _nums = new();
方法参数Process(new List<string>());Process(new());
throw 表达式throw new ArgumentNullException(...)同样——但类型推断不适用
不能用的情况:var x = new();(无目标类型)、dynamic d = new();(无编译期类型)、方法重载歧义。

协变返回Covariant Returns

C# 8 及之前

abstract class Animal {
  abstract Animal Clone();
}
class Dog : Animal {
  override Animal Clone()
    => new Dog();
}

// 每次都要 cast
Dog d = (Dog)original.Clone();

C# 9

abstract class Animal {
  abstract Animal Clone();
}
class Dog : Animal {
  override Dog Clone()
    => new Dog();
}

// 不需要 cast!
Dog d = original.Clone();
规则说明
只限引用类型class / record / delegate / interface——struct 不行
更具体的类型派生类返回类型必须比基类更具体(有隐式引用转换)
不是泛型协变List<Dog> 不能替代 List<Animal>——那是泛型的事
编译器生成两个方法:① 你写的 override Dog Clone()(真正的方法体);② 隐式桥接 override Animal Clone()(调用① + 向上转型返回)。

相关速查