Chapter 01

C# 13 与 .NET 9 新特性

理解 .NET 平台演进历史,掌握 C# 13 最新语法特性,搭建开发环境并运行第一个 .NET 9 程序。

.NET 平台演进:统一之路

微软的 .NET 历史充满了分裂与统一。早期的 .NET Framework 只能运行在 Windows 上,面向企业级应用;2016 年推出的 .NET Core 是跨平台重写版本,性能大幅提升;2020 年的 .NET 5 正式统一了两条线,此后每年 11 月发布一个新版本(偶数年为 LTS 长期支持版),.NET 9 于 2024 年 11 月发布。

.NET Framework 1.0 (2002) — Windows Only, CLR 1.0 │ ▼ .NET Framework 4.8 (2019) — 终结版本,仍随 Windows 预装 │ .NET Core 1.0 (2016) ──── 跨平台重写,性能优先 │ ▼ .NET Core 3.1 LTS (2019) — 支持 WinForms/WPF │ ▼ .NET 5 (2020) ─────────── 统一品牌,去掉 "Core" │ .NET 6 LTS (2021) ──────── MAUI、Minimal API │ .NET 7 (2022) ──────────── 原生 AOT 预览、Rate Limiting │ .NET 8 LTS (2023) ──────── Blazor 统一模型、Aspire 预览 │ ▼ .NET 9 (2024) ──────────── Arm64 优化、张量原语、新 LINQ 方法 C# 13、HybridCache、Aspire 1.0

核心概念名词解释

CLR — 公共语言运行时 (Common Language Runtime)
.NET 的执行引擎,负责将编译好的 IL(中间语言)代码转换为机器码并执行。CLR 提供内存管理(GC)、类型安全、异常处理、线程管理等核心服务。所有 .NET 语言(C#、F#、VB.NET)编译后都运行在同一 CLR 上,这保证了语言互操作性。
IL — 中间语言 (Intermediate Language)
C# 编译器(Roslyn)将源代码编译成的中间表示,存储在 .dll/.exe 文件中。IL 是与平台无关的字节码,类似 Java 的字节码。运行时 CLR 的 JIT 编译器将 IL 翻译为目标 CPU 的机器码。可以用 ildasmdotnet-ildasm 工具查看 IL 内容。
JIT — 即时编译 (Just-In-Time Compilation)
CLR 的默认执行模式:首次调用一个方法时,将对应的 IL 编译为本机机器码并缓存,后续调用直接执行机器码。.NET 的 JIT(RyuJIT)非常成熟,支持内联、向量化、分层编译(Tiered Compilation)等优化,常规场景下性能接近原生 C++。
AOT — 提前编译 (Ahead-of-Time Compilation)
.NET 7+ 的 Native AOT 功能:在发布时直接将整个应用编译为原生机器码,无需 CLR 和 JIT。优点是启动时间极短(几毫秒)、内存占用低、无需安装 .NET 运行时;缺点是不支持反射/动态代码生成,编译时间较长,生成文件较大。适用于 CLI 工具、云函数、微服务。
GC — 垃圾回收 (Garbage Collection)
.NET 的自动内存管理机制。GC 将托管堆分为三代(Gen 0/1/2):短命对象在 Gen 0 快速回收,长命对象晋升到更高代。.NET 9 的 GC 增加了动态适应内存限制(DAMT)功能,能根据可用内存自动调整堆大小,特别适合容器部署场景。
SDK vs Runtime
SDK(Software Development Kit)包含编译器、CLI 工具(dotnet 命令)和 Runtime;Runtime 只包含运行 .NET 应用所需的 CLR 和基础类库。开发机器安装 SDK,生产服务器可以只安装 Runtime(更小)。Native AOT 发布的应用甚至不需要在目标机器上安装任何 .NET 组件。

.NET 9 性能亮点

.NET 9 在性能方面有显著提升,以下是主要改进:

Arm64 优化

  • RyuJIT 新增 SVE(Scalable Vector Extension)支持
  • Apple Silicon(M 系列)性能大幅提升
  • AWS Graviton、Azure Cobalt 等 Arm64 云实例受益
  • 部分算法在 Arm64 上比 x64 快 2-3x

新的 LINQ 方法

  • CountBy():按键分组计数
  • AggregateBy():按键分组聚合
  • Index():枚举时附带索引
  • OrderDescendingBy():简化倒序排列

张量原语(Tensor Primitives)

System.Numerics.Tensors 是 .NET 9 新增的 NuGet 包,提供 SIMD 加速的张量运算,为 AI/ML 应用提供高性能基础。

using System.Numerics.Tensors;

float[] a = [1f, 2f, 3f, 4f];
float[] b = [10f, 20f, 30f, 40f];
float[] result = new float[4];

// SIMD 加速的向量加法(自动选择 AVX2/SSE/NEON 指令)
TensorPrimitives.Add(a, b, result);
// result: [11, 22, 33, 44]

// 点积运算
float dot = TensorPrimitives.Dot(a, b);
// dot: 300 (1*10 + 2*20 + 3*30 + 4*40)

// Softmax(神经网络激活函数)
TensorPrimitives.SoftMax(a, result);

C# 13 新语法特性

params 集合扩展

C# 13 之前,params 只支持数组。现在可以用于任意集合类型(IEnumerable<T>Span<T>ReadOnlySpan<T> 等),减少堆分配。

// C# 13: params 支持 ReadOnlySpan<T>,零分配
static void PrintAll(params ReadOnlySpan<string> items)
{
    foreach (var item in items)
        Console.WriteLine(item);
}

PrintAll("Alice", "Bob", "Charlie"); // 无堆分配

// 也支持 IEnumerable<T>
static int Sum(params IEnumerable<int> numbers)
    => numbers.Sum();

\e 转义符(ESC 字符)

// C# 13 新增 \e 代表 ESC (U+001B),简化终端颜色控制
string red   = $"\e[31m";
string reset = $"\e[0m";
Console.WriteLine($"{red}错误:连接失败{reset}");

// 等价于之前的写法:
// string red = $"\x1B[31m";  或  $"\u001B[31m";

ref struct 实现接口

C# 13 允许 ref struct(如 Span<T>)实现接口,但接口实例不能装箱为引用类型,保持零分配特性。

interface IParser<T>
{
    T Parse(ReadOnlySpan<char> text);
}

// C# 13: ref struct 可以实现接口
ref struct FastIntParser : IParser<int>
{
    public int Parse(ReadOnlySpan<char> text)
        => int.Parse(text);
}

partial 属性(C# 13)

// C# 13: partial 可用于属性(配合源生成器)
partial class MyViewModel
{
    [ObservableProperty]  // CommunityToolkit.Mvvm 源生成器
    public partial string Name { get; set; }
}

C# 现代语法回顾(C# 9-12)

record 类型

record 是 C# 9 引入的不可变数据类型,自动生成 EqualsGetHashCodeToString 和解构方法,非常适合 DTO、值对象场景。

// record class(引用类型,默认不可变)
public record PersonDto(string Name, int Age);

var p1 = new PersonDto("Alice", 30);
var p2 = p1 with { Age = 31 };  // 非破坏性复制

Console.WriteLine(p1 == p2);  // False(值相等比较)
Console.WriteLine(p1);        // PersonDto { Name = Alice, Age = 30 }

// record struct(值类型,零堆分配)
public readonly record struct Point(double X, double Y);

init-only 属性与对象初始化器

public class Config
{
    public string Host { get; init; } = "localhost";
    public int    Port { get; init; } = 5432;
}

var cfg = new Config { Host = "db.example.com", Port = 5433 };
// cfg.Host = "other"; // 编译错误:init-only 属性只能在初始化器中设置

模式匹配进化

// switch 表达式 + 属性模式 + 关系模式
string Classify(Shape shape) => shape switch
{
    Circle { Radius: > 10 }     => "大圆",
    Circle { Radius: > 0 }      => "小圆",
    Rectangle { Width: var w, Height: var h }
        when w == h              => "正方形",
    Rectangle                   => "矩形",
    null                        => "null",
    _                           => "未知形状"
};

// 列表模式(C# 11+)
bool IsFirstTwo(int[] arr) => arr is [1, 2, ..];
bool HasExactly3(int[] arr) => arr is [_, _, _];

集合表达式(C# 12)

// C# 12 集合表达式:统一的字面量语法
int[] arr    = [1, 2, 3];
List<string> list = ["a", "b", "c"];
Span<int>    span = [1, 2, 3];      // 栈分配,零堆分配

// 展开运算符(..)合并集合
int[] all = [..arr, 4, 5];         // [1, 2, 3, 4, 5]

环境安装

安装 .NET SDK

# macOS(Homebrew)
brew install dotnet

# Windows(winget)
winget install Microsoft.DotNet.SDK.9

# Linux(apt)
wget https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install -y dotnet-sdk-9.0

# 验证安装
dotnet --version   # 9.0.xxx
dotnet --list-sdks
Tip 推荐使用 Visual Studio Code + C# Dev Kit 扩展(微软官方,2023 年发布),或 Visual Studio 2022(Community 版免费),或跨平台的 JetBrains Rider(付费,功能最强)。VS Code 的 C# Dev Kit 提供了代码补全、调试、测试运行器等完整功能,是轻量级首选。

第一个 .NET 9 程序

# 创建新控制台项目
dotnet new console -n HelloDotNet
cd HelloDotNet

# 查看生成的文件
ls -la
# Program.cs  HelloDotNet.csproj

# 运行
dotnet run
// Program.cs — .NET 9 默认使用顶级语句(无 class/Main)

// 隐式 using:自动引入 System、System.Linq、System.Collections.Generic 等
Console.WriteLine("Hello, .NET 9!");

// nullable 引用类型默认启用(csproj 中 <Nullable>enable</Nullable>)
string? maybeNull = null;
string notNull    = maybeNull ?? "default";

// 新 LINQ 方法(.NET 9)
var words = new[] { "apple", "banana", "cherry", "apricot", "blueberry" };

// CountBy: 按首字母统计数量
var countByLetter = words.CountBy(w => w[0]);
foreach (var (letter, count) in countByLetter)
    Console.WriteLine($"{letter}: {count}");
// a: 2, b: 2, c: 1

// Index: 枚举时带索引
foreach (var (index, word) in words.Index())
    Console.WriteLine($"[{index}] {word}");

.csproj 文件解读

<!-- HelloDotNet.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <!-- 目标框架 -->
    <TargetFramework>net9.0</TargetFramework>
    <!-- 启用隐式 using 引入 -->
    <ImplicitUsings>enable</ImplicitUsings>
    <!-- 启用 nullable 引用类型检查 -->
    <Nullable>enable</Nullable>
    <!-- 发布为独立可执行文件 -->
    <PublishSingleFile>true</PublishSingleFile>
    <!-- 启用 Native AOT(可选)-->
    <!-- <PublishAot>true</PublishAot> -->
  </PropertyGroup>
</Project>
本章小结 .NET 9 是微软平台统一之路的最新里程碑,C# 13 的 params 集合扩展、\e 转义符、ref struct 接口支持都在提升性能和开发体验。CLR/JIT/AOT 三种执行模式各有适用场景——日常应用用 JIT,启动性能敏感的微服务/CLI 用 Native AOT。下一章将深入 C# 语言核心:类型系统、泛型、LINQ 和模式匹配。