c# 是一种由 microsoft 开发的面向对象的编程语言,它最初于 2000 年发布,并在随后的版本中不断更新和改进。自c# 7.0以来,c#语言在类型系统方面引入了众多新数据类型、类型构造和语言特性,以提升性能、类型安全性和开发效率。本文全面整理了从c# 7.0到c# 14.0(截至2025年4月,c# 14.0为预览版)类型系统的新增内容,包括值元组、span<t>
、readonlyspan<t>
、memory<t>
、readonlymemory<t>
、可空引用类型、记录、本机大小整数、记录结构、内联数组,以及其他增强(如只读结构、泛型数学支持)。
版本概览
以下是c# 7.0至c# 14.0中类型系统新增或增强的主要内容:
c# 版本 | 新增/增强内容 | 发布年份 | 描述 |
---|---|---|---|
7.0 | 值元组(value tuples) | 2017 | 轻量级数据结构,支持多值返回和解构 |
7.2 | span, readonlyspan, 只读结构, 引用结构 | 2017 | 高性能内存操作和不可变/栈分配结构体 |
8.0 | 可空引用类型, memory, readonlymemory | 2019 | 空值安全性和托管内存块 |
9.0 | 记录, 本机大小整数, 初始化器专用类型 | 2020 | 值语义引用类型、本机整数和不可变属性 |
10.0 | 记录结构, 全局 using 指令 | 2021 | 值类型记录和简化类型引用 |
11.0 | 必需成员, 泛型数学支持, 文件局部类型 | 2022 | 强制初始化、泛型运算和类型作用域限制 |
12.0 | 内联数组 | 2023 | 固定大小数组结构,优化性能 |
13.0 | 参数集合扩展, 引用结构接口支持, 部分属性 | 2024 | 扩展params、ref struct接口和部分属性定义 |
14.0 | field 关键字, 隐式 span 转换, nameof 增强, lambda 参数修饰符, partial 成员扩展, 空条件赋值 | 2025 | 增强属性访问、span 使用、泛型处理、lambda 表达、partial 类型和空值处理 |
以下按版本逐一详述,每节包含特性表格、代码示例和分析。
c# 7.0:值元组
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
值元组 (value tuples) | 轻量级值类型,支持多值返回、命名元素和解构 | 方法返回多个值、临时数据分组 | 值类型,栈分配;.net framework需引用system.valuetuple包 |
概述
值元组基于system.valuetuple
,允许方法返回多个值,支持命名元素和解构,简化数据传递。
语法
声明:(type1, type2, ...) tuplename = (value1, value2, ...);
命名元素:(type1 name1, type2 name2, ...) tuplename = (value1, value2, ...);
解构:var (var1, var2, ...) = tuplename;
示例代码
public(intid,stringname)getperson(){return(1,"alice");}varperson=getperson();console.writeline($"id:{person.id},name:{person.name}");//解构var(id,name)=getperson();console.writeline($"id:{id},name:{name}");
适用场景
方法返回多个相关值。
临时数据分组,无需定义类或结构。
解构赋值,简化代码。
注意事项
值类型,适合轻量数据。
.net framework项目需引用system.valuetuple nuget包。
c# 7.2:span, readonlyspan, 只读结构, 引用结构
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
span | 表示连续内存块的引用,支持读写 | 高性能数组/内存操作 | ref struct,栈分配,生命周期限制 |
readonlyspan | 只读连续内存块引用 | 高性能只读操作 | 同上,需确保内存边界安全 |
只读结构 (readonly struct) | 不可变结构体,优化性能 | 不可变数据结构 | 所有实例字段必须只读 |
引用结构 (ref struct) | 栈分配结构体 | 高性能内存管理 | 不可boxing或作为接口实现 |
概述
span<t>
和readonlyspan<t>
是高性能值类型,表示连续内存块引用,适合数组和本机内存操作。readonly struct
确保结构体不可变,ref struct
限制为栈分配,支持span<t>
等类型。
语法
span: span<t> span = collection.asspan();
readonlyspan: readonlyspan<t> readonlyspan = collection.asspan();
只读结构: readonly struct structname { ... }
引用结构: ref struct structname { ... }
示例代码
//span<t>和readonlyspan<t>int[]numbers=[1,2,3,4,5];span<int>span =numbers.asspan(1,3);span[0]=10;console.writeline(string.join(",",span.toarray()));//10,3,4readonlyspan<char>text="hello".asspan();console.writeline(text.slice(0,2).tostring());//he//只读结构readonlystructpoint{publicintx{get;init;}publicinty{get;init;}}pointpoint=new(){x=1,y=2};console.writeline($"({point.x},{point.y})");//(1,2)//引用结构refstructbuffer{publicspan<int>data;publicbuffer(span<int>data)=>data=data;}bufferbuffer=new(numbers.asspan());buffer.data[0]=10;console.writeline(numbers[0]);//10
适用场景
高性能字符串解析、缓冲区处理。
不可变数据结构(只读结构)。
避免堆分配(引用结构)。
注意事项
span<t>
和readonlyspan<t>
不可用于异步方法。
ref struct
限制严格,需管理生命周期。
c# 8.0:可空引用类型, memory, readonlymemory
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
可空引用类型 | 引用类型可标记为可空,默认非null | 增强空值安全性 | 需启用可空上下文,处理编译器警告 |
memory | 托管内存块,支持读写 | 异步和高性能内存操作 | 适合异步场景,需管理生命周期 |
readonlymemory | 只读托管内存块 | 只读异步内存操作 | 同上 |
概述
可空引用类型通过?
后缀指定引用类型是否可为null,减少空引用异常。memory<t>
和readonlymemory<t>
表示托管内存块,支持异步场景。
语法
可空引用类型: string? nullable; string nonnullable;
memory: memory<t> memory = collection.asmemory();
readonlymemory: readonlymemory<t> readonlymemory = collection.asmemory();
示例代码
//可空引用类型#nullableenablestringnonnullable="hello";string?nullable=null;if(nullable!=null){console.writeline(nullable.length);}//memory<t>和readonlymemory<t>int[]numbers=[1,2,3,4,5];memory<int>memory=numbers.asmemory(1,3);span<int>span =memory.span;span[0]=10;console.writeline(string.join(",",memory.toarray()));//10,3,4readonlymemory<char>text="hello".asmemory();console.writeline(text.slice(0,2).span.tostring());//he
适用场景
增强空值安全性(可空引用类型)。
异步内存操作(memory)。
只读数据传递(readonlymemory)。
注意事项
可空引用类型需显式启用。
memory生命周期需管理。
c# 9.0:记录, 本机大小整数, 初始化器专用类型
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
记录 (records) | 具有值语义的引用类型,默认不可变 | 数据建模,值相等性 | 默认不可变,可添加可变行为 |
本机大小整数 (nint, nuint) | 本机大小整数,映射intptr/uintptr | 本机代码互操作 | 平台依赖,需考虑兼容性 |
初始化器专用类型 (init-only setters) | 初始化后不可变属性 | 不可变数据模型 | 仅初始化时可赋值 |
概述
记录是具有值语义的引用类型,自动实现相等性。nint
和nuint
支持本机大小整数。init
修饰符增强属性不可变性。
语法
记录: public record classname(type1 property1, ...);
本机大小整数: nint nativeint; nuint nativeuint;
init-only: public type property { get; init; }
示例代码
//记录publicrecordperson(stringfirstname,stringlastname);varperson1=newperson("alice","smith");varperson2=newperson("alice","smith");console.writeline(person1==person2);//truevarperson3=person1with{lastname="johnson"};console.writeline(person3);//person{firstname=alice,lastname=johnson}//本机大小整数nintnativeint=42;nuintnativeuint=42u;console.writeline($"nativeint:{nativeint},nativeuint:{nativeuint}");//初始化器专用类型publicclassstudent{publicstringname{get;init;}}varstudent=newstudent{name="alice"};console.writeline(student.name);//alice
适用场景
数据传输对象(记录)。
本机代码互操作(nint, nuint)。
不可变数据模型(init-only)。
注意事项
记录支持继承,需保持值语义。
本机大小整数平台依赖。
c# 10.0:记录结构, 全局 using 指令
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
记录结构 (record structs) | 值类型的记录,结合值语义和性能 | 小型数据结构 | 值类型,复制成本需考虑 |
全局 using 指令 | 全局导入命名空间 | 简化类型引用 | 需平衡代码可读性 |
概述
记录结构将记录特性扩展到值类型,结合值语义和性能。全局using
简化类型引用。
语法
记录结构: public record struct structname(type1 property1, ...);
全局 using: global using system;
示例代码
//记录结构publicrecordstructpoint(intx,inty);varpoint1=newpoint(1,2);varpoint2=newpoint(1,2);console.writeline(point1==point2);//truevarpoint3=point1with{x=3};console.writeline(point3);//point{x=3,y=2}//全局using(假设已在文件顶部)console.writeline("hello,world!");//无需显式usingsystem
适用场景
值类型数据建模(记录结构)。
大型项目命名空间管理(全局 using)。
注意事项
记录结构复制成本需关注。
全局 using 需谨慎使用。
c# 11.0:必需成员, 泛型数学支持, 文件局部类型
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
必需成员 (required members) | 强制成员初始化 | 确保关键字段初始化 | 需配合初始化器或构造函数 |
泛型数学支持 | 静态抽象接口成员支持泛型运算 | 泛型算法库 | 需运行时支持(.net 7+) |
文件局部类型 (file modifier) | 限制类型作用域至文件 | 隔离辅助类型 | 仅限文件作用域 |
概述
required
修饰符强制成员初始化。泛型数学支持通过接口实现数值运算。file
修饰符限制类型作用域。
语法
必需成员: public required type property { get; set; }
泛型数学: interface inumber<t> { static abstract t operator +(t, t); }
文件局部类型: file class classname { ... }
示例代码
//必需成员publicclassperson{publicrequiredstringname{get;set;}}varperson=newperson{name="alice"};console.writeline(person.name);//alice//泛型数学支持publicinterfaceinumber<t>wheret:inumber<t>{staticabstracttadd(tleft,tright);}publicreadonlystructmynumber:inumber<mynumber>{publicintvalue{get;init;}publicmynumber(intvalue)=>value=value;publicstaticmynumberadd(mynumberleft,mynumberright)=>new(left.value+right.value);}mynumbera=new(1);mynumberb=new(2);varresult=mynumber.add(a,b);console.writeline(result.value);//3//文件局部类型fileclasshelper{publicstaticvoidlog(stringmessage)=>console.writeline(message);}helper.log("test");
适用场景
api 设计(必需成员)。
泛型数值计算(泛型数学)。
代码生成(文件局部类型)。
注意事项
必需成员需明确初始化。
泛型数学需运行时支持。
c# 12.0:内联数组
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
内联数组 (inline arrays) | 固定大小数组结构,栈分配 | 高性能固定大小数组 | 固定大小,仅限结构体内 |
概述
内联数组通过[inlinearray]
特性定义固定大小数组结构,优化性能。
语法
[inlinearray(length)]publicstructstructname{privateelementtype_element0;}
示例代码
[inlinearray(10)]publicstructbuffer{privateint_element0;}bufferbuffer=new();buffer[0]=1;buffer[9]=10;console.writeline(buffer[0]);//1
适用场景
高性能计算。
替代不安全固定缓冲区。
注意事项
固定大小,运行时不可调整。
c# 13.0:参数集合扩展, 引用结构接口支持, 部分属性
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
参数集合扩展 (params span等) | 扩展params支持span等 | 高性能参数传递 | 需确保span生命周期 |
引用结构接口支持 | 允许ref struct实现接口 | 扩展ref struct能力 | 仍受ref struct限制 |
部分属性 (partial properties) | 支持partial类型部分属性 | 代码生成 | 需确保定义一致 |
概述
参数集合扩展支持span<t>
等类型。ref struct
可实现接口。部分属性支持分文件定义。
语法
参数集合: void method(params span<t> spans);
引用结构接口: ref struct structname : iinterface { ... }
部分属性: public partial type property { get; set; }
示例代码
//参数集合扩展publicvoidprocess(paramsspan<int>spans){foreach(varspan inspans)console.writeline(string.join(",",span.toarray()));}int[]numbers=[1,2,3];process(numbers.asspan(0,2),numbers.asspan(2,1));//1,2和3//引用结构接口支持publicinterfaceibuffer{voidprocess();}refstructbuffer:ibuffer{publicspan<int>data;publicbuffer(span<int>data)=>data=data;publicvoidprocess()=>data[0]=10;}bufferbuffer=new(numbers.asspan());buffer.process();console.writeline(numbers[0]);//10//部分属性publicpartialclassperson{publicpartialstringname{get;set;}}publicpartialclassperson{publicpartialstringname{get=>_name;set=>_name=value;}privatestring_name;}varperson=newperson{name="alice"};console.writeline(person.name);//alice
适用场景
高性能参数传递(参数集合)。
扩展ref struct
(接口支持)。
代码生成(部分属性)。
注意事项
参数集合需管理span生命周期。
部分属性需确保一致性。
c# 14.0:field
关键字, 隐式 span 转换, nameof
增强, lambda 参数修饰符, partial 成员扩展, 空条件赋值
特性表格
类型/构造 | 描述 | 主要用途 | 注意事项 |
---|---|---|---|
field 关键字 | 允许在属性访问器中直接访问 backing field | 简化属性实现 | 可能与现有字段名冲突,需使用 @field 或 this.field 区分 |
隐式 span 转换 | 支持 span<t> 、readonlyspan<t> 与数组间的隐式转换 | 更自然地使用 span 类型 | 需注意 span 的生命周期 |
nameof 支持未绑定泛型 | 允许 nameof 使用未绑定泛型类型,如 nameof(list<>) | 泛型编程中的类型名称获取 | - |
lambda 参数修饰符 | 允许 lambda 参数使用 ref 、out 等修饰符,无需指定类型 | 增强 lambda 表达式的灵活性 | params 仍需指定类型 |
partial 构造函数和事件 | 扩展 partial 成员到实例构造函数和事件 | 分离定义和实现,适合代码生成 | 需确保 defining 和 implementing 声明一致 |
空条件赋值 | 允许在赋值左侧使用 ?. 和 ?[] ,仅在左侧非 null 时赋值 | 简化 null 检查 | 不支持 ++ 和 -- |
概述
c# 14.0(预计2025年随.net 10发布,截至2025年4月为预览版)引入了一系列语言特性,旨在提高开发效率和代码可读性,包括 field
关键字、隐式 span 转换、nameof
增强、lambda 参数修饰符、partial 成员扩展和空条件赋值。虽然未引入全新数据类型,但这些特性显著增强了现有类型的用法。
field
关键字概述
field
关键字允许在属性访问器中直接访问编译器生成的 backing field,无需显式声明。
示例代码
publicclassperson{publicstringname{get=>field;set=>field=value?.trim();}}varperson=newperson{name="alice"};console.writeline(person.name);//alice
适用场景
简化属性实现,特别是需要对 setter 进行处理时。
注意事项
如果类中已有名为 field
的字段,需使用 @field
或 this.field
区分。
作为c# 13.0的预览特性,c# 14.0正式支持,详见field 关键字。
隐式 span 转换概述
c# 14.0 为 span<t>
和 readonlyspan<t>
提供了与数组的隐式转换,使其使用更加自然。
示例代码
span<int>span =newint[]{1,2,3};int[]array=span.toarray();console.writeline(string.join(",",array));//1,2,3
适用场景
高性能场景中,减少显式转换。
与数组和 span 类型交互。
注意事项
需确保 span 的生命周期管理,详见span 转换。
nameof
支持未绑定泛型概述
允许 nameof
操作符使用未绑定泛型类型。
示例代码
stringlistname=nameof(list<>);console.writeline(listname);//list
适用场景
泛型编程中,获取类型名称。
注意事项
简单但强大的增强,适合反射场景。
lambda 参数修饰符概述
允许在 lambda 表达式中为参数添加修饰符,如 ref
、out
等,无需指定类型。
示例代码
varincrement=(refintx)=>x++;intnum=5;increment(refnum);console.writeline(num);//6
适用场景
需要在 lambda 中修改外部变量。
注意事项
params
仍需指定类型,详见lambda 表达式。
partial 构造函数和事件概述
扩展 partial 成员到实例构造函数和事件,允许在 partial 类型中分离定义和实现。
示例代码
//file1.cspublicpartialclassmyclass{publicpartialmyclass(intx);publicpartialeventeventhandlermyevent;}//file2.cspublicpartialclassmyclass{publicpartialmyclass(intx){}publicpartialeventeventhandlermyevent;}
适用场景
代码生成场景,如 ui 设计器。
注意事项
需确保 defining 和 implementing 声明一致,详见partial 成员。
空条件赋值概述
允许在赋值语句的左侧使用 ?.
和 ?[]
,仅当左侧非 null 时执行赋值。
示例代码
string?text=null;text?.length=5;//不执行赋值list<int>?list=null;list?[0]=10;//不执行赋值list=newlist<int>{0};list?[0]=10;//执行赋值,list[0]=10console.writeline(list[0]);//10
适用场景
简化 null 检查,避免 nullreferenceexception。
注意事项
不支持 ++
和 --
操作,详见空条件赋值。
结语
c# 7.0至c# 14.0的类型系统新增内容涵盖了值元组、span、readonlyspan、memory、readonlymemory、可空引用类型、记录、本机大小整数、记录结构、内联数组等数据类型,以及只读结构、引用结构、必需成员、泛型数学支持等增强。c# 14.0通过field
关键字、隐式 span 转换等特性进一步优化了现有类型的用法。这些特性满足了从高性能内存管理到类型安全建模的多种需求。资深c#工程师可根据场景选择类型,如使用span优化性能,记录建模数据。由于c# 14.0尚在预览阶段,建议关注dotnet/roslyn以获取最新更新。
到此这篇关于c#类型系统从7.0到14.0的发展历程和版本特性的文章就介绍到这了,更多相关c#高性能开发之类型系统:从 c# 7.0 到 c# 14 的类型系统演进全景内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论