Elytra
Blog2026

C# 版本史:从 1.0 到 14,语言特性如何演进

梳理 C# 自 2002 年以来的版本脉络——从传统 OO 到泛型、LINQ、async/await、模式匹配、record 与 Span,再到 C# 14 的 extension members 与 C# 15 预览。

随笔
GPT 5.6+1
csharpdotnethistorylanguagelinqasync

如果你写过一段时间 C#,很可能经历过这样的困惑:

这段 record 语法是哪年加的?async/await 之前大家怎么写异步?为什么 Unity 项目里用不了最新的语言特性?

这些问题指向同一件事:C# 不是一成不变的「微软版 Java」,而是一套持续演进的语言。 从 2002 年的 1.0 到 2025 年的 14,几乎每一版都在回答同一个问题——怎样让程序员写得更少、更安全、更快。

我不打算把它写成逐条罗列的 changelog。C# 二十多年有一条很清晰的主线:从 Java 风格的传统 OO 语言出发,逐步加入泛型、函数式编程、LINQ、异步、模式匹配、值语义、Span<T> 等高性能内存编程能力,正在变成一门兼顾高级抽象与底层性能的现代通用语言。

本文专注 语言特性 的演进脉络。若你想了解 .NET 为何一度锁在 Windows、开源为何来得偏晚,可以读 .NET 的平台弯路;若关心 Unity 里 Mono、IL2CPP 与 CoreCLR 的关系,见 Unity 的 C# 运行时

资料范围

本文资料整理截至 2026 年 9 月 21 日

  • 最新正式版:C# 14,2025 年 11 月随 .NET 10 发布。1
  • 最新预览版:C# 15 Preview,随 .NET 11 Preview 开发,计划 2026 年 11 月正式发布;已公开 Union Types、Closed Hierarchies、内存安全模型重构等特性。2

版本特性与发布时间以 Microsoft Learn 官方版本史 为准。3

版本历史总览

下表按发布时间排列。第三列「配套运行时」是 默认绑定 关系;早期 C# 也可在较新的 Framework 上编译,但新特性往往依赖对应 CLR(运行时引擎)与 BCL(Base Class Library,基础类库,即 System.* 等标准 API)。45

版本时间配套运行时最有代表性的变化
C# 1.02002-01.NET Framework 1.0类、接口、结构体、属性、委托、事件、特性、异常、GC;外观像 Java,但已有 struct / ref / out / unsafe 等差异化设计
C# 1.22003-04.NET Framework 1.1小幅修正;foreachIEnumerator 实现 IDisposable 时自动调用 Dispose
C# 2.02005-11.NET Framework 2.0泛型Nullable<T>、迭代器(yield)、匿名方法、分部类;CLR 级 reified generics(具化泛型),告别 ArrayList + 强转
C# 3.02007-11.NET Framework 3.5LINQ、Lambda、扩展方法、表达式树(expression trees)、var、匿名类型;C# 从纯 OO 转向 OO + 函数式 混合范式,ORM/动态查询的基础设施
C# 4.02010-04.NET Framework 4.0dynamic、命名/可选参数、泛型协变/逆变;主要服务 COM 互操作与动态场景
C# 5.02012-08.NET Framework 4.5async / await;编译器生成状态机,异步从 callback / BeginXXX 变成近似同步的写法
C# 6.02015-07.NET Framework 4.6字符串插值、?. 空传播、nameof、表达式体成员;Roslyn 编译器开源,编译器即服务
C# 7.02017-03.NET Framework 4.7 / .NET Core 1.x元组、模式匹配、局部函数、ref return、discard(_
C# 7.12017-08.NET Core 2.0async Main、default literal、元组元素名推断;首次引入小版本发布与 LangVersion 配置
C# 7.22017-11VS 2017 15.5+ref structreadonly structin / ref readonlySpan<T> 时代的基础设施,栈分配与零拷贝切片
C# 7.32018-05.NET Core 2.1 / .NET Framework 4.8stackalloc / fixed / 泛型约束性能增强;元组 ==、属性 backing field 特性
C# 8.02019-09.NET Core 3.0可空引用类型(nullable reference types)、switch 表达式、异步流、索引/范围、默认接口实现;现代 C# 基本成型
C# 9.02020-11.NET 5recordinit、顶层语句、关系/逻辑模式、nint、函数指针;数据建模与算法分离
C# 102021-11.NET 6record struct、global using、文件范围命名空间、插值字符串处理器;年度发布节奏确立
C# 112022-11.NET 7泛型数学(generic math)、static abstract 接口成员、原始字符串字面量、required、列表模式、ref 字段
C# 122023-11.NET 8主构造函数、集合表达式、内联数组(inline arrays)
C# 132024-11.NET 9params 集合、新 System.Threading.Lock 语义、ref struct 可实现接口/作泛型参数、分部属性
C# 142025-11.NET 10扩展成员(extension members)、field 关键字、空条件赋值、Span 隐式转换增强;当前最新稳定版
C# 15 Preview2026(预览).NET 11 PreviewUnion Types、Closed Hierarchies、内存安全模型重构、扩展索引器;计划 2026-11 正式发布,特性仍可能变动

语言版本 ≠ 你能用的特性

编译器认某段语法,不代表目标运行时和库一定支持。C# 8 的可空引用类型、C# 9 的 record、C# 11 的泛型数学,都依赖对应的 BCL 与 CLR 能力。Unity 等使用旧 Mono 分支的环境,往往卡在 C# 9 甚至更低——这是 运行时 的限制,不是语法本身的问题。

演化主线

C# 1 传统 OO C# 2 泛型 C# 3 LINQ C# 5 async C# 7 ref 与 Span C# 8 可空与模式匹配 C# 9 record C# 11 泛型数学 C# 14 扩展成员 C# 15 Union 预览

核心论点可以概括为:

C# 的二十多年,并不是不断堆砌语法糖,而是在不断消除「高级抽象」和「底层性能」之间的边界。

C# 1.0:一门现代化的 OO 语言

C# 1.0 于 2002 年 正式发布,目标是做一门简单、现代、类型安全、面向对象的通用语言。3

当年的写法看起来确实很像 Java:

class Player
{
    public string Name { get; set; }

    public void Move() { }
}

但 C# 从一开始就加入了 Java 当时没有、或设计方式明显不同的东西:struct、属性、委托/事件、运算符重载、特性、ref/outunsafe

尤其是 属性、委托/事件、struct、ref/out,后来一直成为 C# 很有辨识度的语言特性。微软官方也把 C# 1.0 描述为相较现代 C# 相当冗长的语言——当时没有泛型、LINQ、Lambda、async/awaitvar、模式匹配、可空引用类型。3

第一场革命:泛型与 LINQ

C# 2.0:泛型真正改变了类型系统

2005 年 C# 2.0 是第一个巨大飞跃。此前:

ArrayList list = new ArrayList();
list.Add(123);
int value = (int)list[0];  // 运行时才能发现类型错误

C# 2:

List<int> list = new();
list.Add(123);
int value = list[0];  // 编译期类型安全

这不仅是语法糖,而是 CLR 本身支持的 reified generics(具化泛型)——与 Java 的 type erasure(类型擦除)形成鲜明对比。此外还有:

  • Nullable<T>:值类型可表达「没有值」(int? 等价于 Nullable<int>
  • yield 迭代器:用 yield return 懒生成序列,编译器帮你实现 IEnumerable<T>
  • 分部类(partial class):同一个类拆到多个文件编译,常见于 WinForms / 源生成器代码
  • getter/setter 独立访问控制public int X { get; private set; }
IEnumerable<int> Range()
{
    yield return 1;
    yield return 2;
}

C# 3.0:可能是历史上最重要的一版

2007 年 C# 3.0 值得单独用一大章。今天我们认为「理所当然」的 C#,很大一部分都是 C# 3 带来的:

Lambda
LINQ
扩展方法
表达式树
var
匿名类型
对象/集合初始化器
自动属性
var adults = users
    .Where(x => x.Age >= 18)
    .OrderBy(x => x.Name)
    .Select(x => x.Name);

背后实际上是多项语言特性一起工作:

Lambda → 扩展方法 → 泛型 → 类型推断 → LINQ

更厉害的是,Lambda 不一定编译成委托,也可以编译成 表达式树

Expression<Func<User, bool>> expr = user => user.Age >= 18;

这成为 Entity Framework、LINQ to SQL、ORM 动态查询生成的基础。微软官方直接把 C# 3.0 称为一次重大变化,认为它开始让 C# 成为 OO + 函数式 的混合语言。3

第二场革命:动态与异步

C# 4.0:dynamic

2010 年 C# 4.0 还加入了命名/可选参数、泛型协变/逆变,但最值得单独说的是 dynamic

普通 C# 变量在编译期就绑定了类型——你写 value.Foo(),编译器会检查 value 的类型上有没有 Foo 这个方法,没有就直接报错。dynamic 把这一步推迟到 运行时:编译器只确认「这是个动态值」,成员解析交给 DLR(Dynamic Language Runtime) 在运行期根据对象的实际类型来决定。6

dynamic value = GetSomething();
value.Foo();  // 编译通过;运行时再找 Foo

Foo(name: "Alice", age: 20);  // 命名参数

如果运行时对象上 根本没有 Foo,不会变成编译错误,而是抛出 RuntimeBinderException

dynamic value = "hello";
value.Foo();  // 编译 OK
// 运行时报错:'string' does not contain a definition for 'Foo'

参数个数或类型对不上,同样在运行期才暴露。这和 JavaScript、Python 等动态语言的体验类似——灵活,但失去了 C# 静态类型检查的主要安全感。因此 dynamic 主要用在 COM 互操作(Office、旧式 Windows API)、与 Python/IronPython 等动态语言交互、或 JSON 反序列化后临时操作等「编译期实在无法确定类型」的场景。日常业务代码里很少大面积使用。

C# 4.0 同版的其他特性

命名参数与可选参数 让你调用方法时可以按名字传参、省略有默认值的参数,减少大量重载:

void Log(string message, int level = 1) { }

Log("ok");                              // 可选参数:level 取默认值 1
Log(message: "warn", level: 2);         // 命名参数:不必按声明顺序

泛型协变与逆变(variance)解决的是:泛型类型之间能不能像普通继承那样赋值。C# 2 的泛型默认是 不变(invariant)的——List<string> 不能赋给 List<object>,哪怕 stringobject 的子类。

C# 4 在 接口和委托 上引入 out / in 修饰类型参数:

  • 协变(covariance,out TT 只作为输出(返回值等),则子类型的泛型可以赋给父类型的泛型
  • 逆变(contravariance,in TT 只作为输入(参数等),则父类型的泛型可以赋给子类型的泛型
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;  // OK:IEnumerable<out T> 协变

Action<object> actObj = o => Console.WriteLine(o);
Action<string> actStr = actObj;       // OK:Action<in T> 逆变

直觉上:协变像「只读容器可以放宽类型」,逆变像「只写回调可以收窄类型」。类(如 List<T>)本身仍是不变的——这是有意设计,避免运行期类型安全问题。

C# 5.0:async / await

2012 年 C# 5 的主题几乎只有一个。此前异步代码充满 callback、BeginXXX / EndXXX、continuation;现在可以写成近似同步代码,编译器自动生成状态机:

async Task<string> DownloadAsync()
{
    return await httpClient.GetStringAsync(url);
}

微软官方明确称 async / await 是 C# 5 的真正主角。3 后来 JavaScript、Python、Rust、Swift 等语言都形成了类似的 async 模型。

第三阶段:Roslyn 与「让代码变少」

C# 6:语言开始明显追求开发体验

2015 年 C# 6 单独看没有 LINQ 或 async 那样的「核弹级」功能,但形成了后来非常明确的设计方向:减少样板代码

$"Hello {name}"                    // 字符串插值
player?.Weapon?.Fire()             // 空传播
nameof(Player)                     // 编译期安全的名称
public int Damage => Attack * 2;   // 表达式体成员

还有一个历史意义重大的事件:Roslyn——C# 编译器被重写为 C# 编写并开源,编译器本身也成为 API(语法树、语义模型、分析器、源生成器等)。3

第四阶段:模式匹配与高性能 C#

C# 7:模式匹配与 ref 语义

2017 年 C# 7 引入模式匹配与元组解构:

if (obj is Player player) { /* ... */ }

(string name, int age) GetUser() => ("Alice", 20);

还有局部函数、discard _、二进制字面量、throw 表达式、ref 局部变量 / ref 返回——C# 开始认真解决「高级语言抽象与底层性能之间的矛盾」:

ref Vector3 GetPosition() => ref position;

C# 7.2 / 7.3:Span 时代的基础设施

这一阶段非常值得游戏开发者关注。出现 readonly structref structinref readonlystackalloc 改进:

Span<int> values = stackalloc int[128];

开始允许栈分配、零拷贝切片、避免 GC、ref 语义,同时保留类型安全——为 Span<T>Memory<T>System.IO.Pipelines、高性能网络、游戏引擎、序列化铺路。

C# 8:现代 C# 基本成型

2019 年 C# 8 又是一个超级大版本,也是第一个主要面向 .NET Core 的大版本。

可空引用类型

string? name = GetName();
Console.WriteLine(name.Length);  // 编译器警告:Possible null reference

这不是 Nullable<T>,而是编译器进行静态空流分析,系统性对付 NullReferenceException

switch 表达式与模式匹配

// 以前
switch (state)
{
    case State.Idle: return 0;
    case State.Run:  return 1;
    default:         return -1;
}

// C# 8
return state switch
{
    State.Idle => 0,
    State.Run  => 1,
    _          => -1
};

此外还有异步流(IAsyncEnumerable<T>)、索引/范围(array[^1]array[1..5])、using 声明、默认接口实现、??=3

C# 9:数据建模

2020 年 C# 9 引入 record——自动获得值相等、ToString、解构、with

public record Player(string Name, int Health);

var player2 = player1 with { Health = 50 };

init 仅初始化 setter 表示属性只能在对象构造阶段赋值,之后只读;配合 with 做非破坏性复制(改一个字段、其余照抄)。还有顶层语句、关系/逻辑模式(value is > 0 and < 100)、nint/nuint、函数指针等,让 C# 终于拥有简洁的不可变数据建模能力。3

C# 10–12:年度节奏下的现代化

C# 10(2021) 继续删除仪式性代码:文件范围命名空间(namespace Ethertia;)、global using、record struct,以及容易被忽视但对性能很重要的 插值字符串处理器——表面语法更高级,生成代码反而可以更高效。

C# 11(2022)泛型数学 通过 static abstract 接口成员解决 T + T 不能写的问题:

static T Add<T>(T a, T b) where T : INumber<T> => a + b;

还有原始字符串字面量(""" 多行字符串)、required 成员、列表模式、file 局部类型、ref 字段、scoped ref

C# 12(2023) 把主构造函数扩展到任意 class/struct,并引入集合表达式:

// 以前
class Player
{
    private readonly string name;
    public Player(string name) => this.name = name;
}

// C# 12
class Player(string name) { }

int[] values = [1, 2, 3];
int[] all = [..a, ..b];  // spread 展开

C# 13–14:拆掉限制、扩展成员

C# 13(2024)params 不再局限于数组,可用于 Span<T> 等集合类型;新的 System.Threading.Locklock 语句生成基于作用域的逻辑;ref struct 可实现接口、可作为泛型参数——C# 团队在不断拆掉 GC / ref struct / 泛型之间过去留下的限制。

C# 14(2025) 是当前最新稳定版,重点是 扩展成员(extension members)——从扩展方法进化到可扩展属性、运算符等:

// C# 3:只能扩展方法
public static int Foo(this Player player) => player.Health;

// C# 14:extension members(示意)
extension(Player player)
{
    public int HealthPercentage
        => player.Health * 100 / player.MaxHealth;
}

field 关键字简化属性后备字段访问:

public int Health
{
    get;
    set => field = Math.Max(value, 0);
}

还有空条件赋值(player?.Health = 100)、partial 事件/构造函数、Span 隐式转换增强。17

C# 15 Preview:向代数数据类型靠近

预览特性,可能变动

以下 C# 15 内容均处于 Preview,计划随 .NET 11 于 2026 年 11 月正式发布,语法与语义仍可能在后续 preview 中调整。生产项目请勿依赖。2

Union Types(联合类型)

public union Pet(Cat, Dog, Bird);

Pet pet = new Dog("Rex");

var name = pet switch
{
    Dog d  => d.Name,
    Cat c  => c.Name,
    Bird b => b.Name,
    // 无需 _ 默认分支——编译器保证 exhaustive
};

Union 声明值恰好是固定 case 类型之一,彼此不必有继承关系,非常接近 Rust 的 enum 或 TypeScript 联合类型的思想。8

Closed Hierarchies(封闭继承层次)

public closed record class GateState;
public record class Closed : GateState;
public record class Open(float Percent) : GateState;

// switch 覆盖所有直接子类型即可,无需 _
var label = state switch
{
    Closed   => "closed",
    Open o   => $"open {o.Percent}%"
};

closed 修饰的类隐式 abstract,仅允许在同一程序集内派生,编译器因此能做穷尽性检查。9

内存安全模型重构

C# 15 开始重新思考 unsafe 的含义:过去「出现 pointer 即 unsafe」;新设计逐渐变成「真正访问无法被编译器验证的内存,才属于 unsafe 操作」。指针类型本身未必 unsafe,*pp->fieldp[index] 等解引用才需要 unsafe 上下文——更接近 Rust「哪些操作破坏了编译器能证明的安全边界」的哲学。10

附:几个文中点到、值得一句话的概念

概念一句话
reified generics泛型类型信息在运行时保留,List<int>List<string> 是两种不同的类型
表达式树Lambda 不编译成 IL,而是编译成可遍历、可翻译的 AST,供 ORM 等转成 SQL
协变 / 逆变见上文 C# 4.0;out T 协变、in T 逆变,仅适用于接口与委托
ref struct必须在栈上分配、不能装箱、不能进堆;Span<T> 的载体,服务零分配场景
init属性只能在构造函数或对象初始化器里赋值,之后不可改
withrecord 的非破坏性复制:copy with { Field = newValue }
主构造函数构造参数直接写在类型声明上,编译器生成字段与构造函数体
集合表达式[1, 2, ..other] 统一初始化数组、ListSpan 等, .. 为 spread

横切主题:三条线在版本间接力

模式匹配

版本里程碑
C# 7is 模式、switch 模式、out 变量
C# 8switch 表达式、属性/元组/位置模式
C# 9关系模式、and/or/notis not null
C# 11列表模式
C# 15 Previewunion 模式、closed hierarchy 穷尽 switch

值类型与性能

版本里程碑
C# 7.2ref structin / ref readonly
C# 8stackalloc、Index/Range
C# 9nint、function pointers
C# 11ref fields、scoped ref
C# 12内联数组
C# 13ref struct 泛型约束、params Span<T>
C# 14Span 更多隐式转换

数据类与少写样板

版本里程碑
C# 3自动属性、对象/集合初始化器
C# 6表达式体成员、字符串插值
C# 9recordinitwith
C# 10record struct
C# 12主构造函数、集合表达式
C# 14field 关键字、partial 构造函数

实用:如何指定语言版本

默认情况下,语言版本由目标框架(TFM)决定4

<PropertyGroup>
  <TargetFramework>net10.0</TargetFramework>
  <!-- 默认即 C# 14 -->
</PropertyGroup>

需要显式指定时,使用 LangVersion

<LangVersion>13.0</LangVersion>    <!-- 锁定 C# 13 -->
<LangVersion>latest</LangVersion>  <!-- 已安装 SDK 的最新版 -->
<LangVersion>preview</LangVersion> <!-- 含 C# 15 等预览特性 -->
目标框架默认 C# 版本
.NET 11.x(预览)C# 15
.NET 10.xC# 14
.NET 9.xC# 13
.NET 8.xC# 12
.NET 6.xC# 10
.NET Framework(全部)C# 7.3

写给 Unity 开发者

Unity 的 C# 语言版本上限,取决于 Editor/Player 使用的脚本后端与 Roslyn 版本,而不是你本机装的最新 .NET SDK。Unity 6 及更早版本通常卡在 C# 9 左右;Unity 7 迁移 CoreCLR 后,才有机会跟上 C# 14 与现代 BCL。详见 Unity 的 C# 运行时

收束

若把 C# 的演进压缩成一条叙事线:

C# 1   → 现代 OO(属性 / 委托 / struct)
C# 2   → 类型系统革命(泛型 / nullable / 迭代器)
C# 3   → 函数式 C#(LINQ / Lambda / 表达式树)
C# 5   → 异步革命(async / await)
C# 6   → Roslyn 与语法现代化
C# 7   → 高性能 C#(ref / ref struct / Span 基础)
C# 8   → 可空引用 + 模式匹配成型
C# 9   → record / 数据导向语法
C# 11  → 泛型数学
C# 12  → 集合表达式 / 主构造函数
C# 13  → ref struct 解限
C# 14  → 扩展成员
C# 15  → Union / closed hierarchy / 内存安全(预览)

理解这条线,比记住每个版本的完整特性列表更有用。若你关心「语言设计激进,为何生态仍被 Java 压着」——那是平台战略的故事,见 .NET 的平台弯路

未纳入正式版的特性状态可在 dotnet/roslyndotnet/csharplang 仓库中跟踪。11

注释

  1. Microsoft Learn,What's new in C# 14。C# 14 为当前最新正式版,需 .NET 10。 2

  2. Microsoft Learn,What's new in C# 15。C# 15 预览特性列表与 .NET 11 配套关系。 2

  3. Microsoft Learn,The history of C#。各版本特性列表、发布时间与官方叙事。 2 3 4 5 6 7 8

  4. Microsoft Learn,C# language versioning。语言版本与目标框架的默认对应关系及 LangVersion 配置。 2

  5. Microsoft Learn,Base Class Library。BCL 是随 .NET 发布的标准类库,与 CLR 并列。

  6. Microsoft Learn,dynamic(C# reference)dynamic 的运行时分派机制与 RuntimeBinderException 行为说明。

  7. .NET Blog,Introducing C# 14。extension members 等 headline 特性的官方介绍。

  8. .NET Blog,Explore union types in C# 15。Union Types 的设计动机与 exhaustive matching 语义。

  9. .NET Blog,Explore new features available in C# 15 preview。Closed Hierarchies 与 Union Types 的关系说明。

  10. .NET 11 Preview 5 Release Notes,C# updates。Memory Safety / unsafe 模型演进(预览阶段)。

  11. GitHub,dotnet/roslyn。Roslyn 编译器仓库,含语言特性实现状态与预览功能跟踪。

On this page