⚡ 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 null、x 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# 8 | C# 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()(调用① + 向上转型返回)。
相关速查