C#高性能開發之類型系統:從 C# 7.0 到 C# 14 的類型系統演進全景
自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 (int id, string name) GetPerson()
{
return (1, "Alice");
}
var person = 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, 4
ReadOnlySpan<char> text = "Hello".AsSpan();
Console.WriteLine(text.Slice(0, 2).ToString()); // He
// 只讀結構
readonly struct Point
{
public int X { get; init; }
public int Y { get; init; }
}
Point point = new() { X = 1, Y = 2 };
Console.WriteLine($"({point.X}, {point.Y})"); // (1, 2)
// 引用結構
ref struct Buffer
{
public Span<int> Data;
public Buffer(Span<int> data) => Data = data;
}
Buffer buffer = 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();
示例代碼
// 可空引用類型
#nullable enable
string nonNullable = "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, 4
ReadOnlyMemory<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; }
示例代碼
// 記錄
public record Person(string FirstName, string LastName);
var person1 = new Person("Alice", "Smith");
var person2 = new Person("Alice", "Smith");
Console.WriteLine(person1 == person2); // True
var person3 = person1 with { LastName = "Johnson" };
Console.WriteLine(person3); // Person { FirstName = Alice, LastName = Johnson }
// 本機大小整數
nint nativeInt = 42;
nuint nativeUInt = 42u;
Console.WriteLine($"Native int: {nativeInt}, Native uint: {nativeUInt}");
// 初始化器專用類型
public class Student
{
public string Name { get; init; }
}
var student = new Student { 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;
示例代碼
// 記錄結構
public record struct Point(int X, int Y);
var point1 = new Point(1, 2);
var point2 = new Point(1, 2);
Console.WriteLine(point1 == point2); // True
var point3 = point1 with { X = 3 };
Console.WriteLine(point3); // Point { X = 3, Y = 2 }
// 全局 using(假設已在文件頂部)
Console.WriteLine("Hello, World!"); // 無需顯式 using System
適用場景
-
值類型數據建模(記錄結構)。 -
大型項目命名空間管理(全局 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 { ... }
示例代碼
// 必需成員
public class Person
{
public required string Name { get; set; }
}
var person = new Person { Name = "Alice" };
Console.WriteLine(person.Name); // Alice
// 泛型數學支持
public interface INumber<T> where T : INumber<T>
{
static abstract T Add(T left, T right);
}
public readonly struct MyNumber : INumber<MyNumber>
{
public int Value { get; init; }
public MyNumber(int value) => Value = value;
public static MyNumber Add(MyNumber left, MyNumber right) => new(left.Value + right.Value);
}
MyNumber a = new(1);
MyNumber b = new(2);
var result = MyNumber.Add(a, b);
Console.WriteLine(result.Value); // 3
// 文件局部類型
file class Helper
{
public static void Log(string message) => Console.WriteLine(message);
}
Helper.Log("Test");
適用場景
-
API 設計(必需成員)。 -
泛型數值計算(泛型數學)。 -
代碼生成(文件局部類型)。
注意事項
-
必需成員需明確初始化。 -
泛型數學需運行時支持。
C# 12.0:內聯數組
特性表格
| 類型/構造 | 描述 | 主要用途 | 注意事項 |
|---|---|---|---|
| 內聯數組 (Inline Arrays) | 固定大小數組結構,棧分配 | 高性能固定大小數組 | 固定大小,僅限結構體內 |
概述
內聯數組通過[InlineArray]特性定義固定大小數組結構,優化性能。
語法
[InlineArray(length)]
public struct StructName
{
private elementType _element0;
}
示例代碼
[InlineArray(10)]
public struct Buffer
{
private int _element0;
}
Buffer buffer = 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; }
示例代碼
// 參數集合擴展
public void Process(params Span<int> spans)
{
foreach (var span in spans)
Console.WriteLine(string.Join(", ", span.ToArray()));
}
int[] numbers = [1, 2, 3];
Process(numbers.AsSpan(0, 2), numbers.AsSpan(2, 1)); // 1, 2 和 3
// 引用結構接口支持
public interface IBuffer
{
void Process();
}
ref struct Buffer : IBuffer
{
public Span<int> Data;
public Buffer(Span<int> data) => Data = data;
public void Process() => Data[0] = 10;
}
Buffer buffer = new(numbers.AsSpan());
buffer.Process();
Console.WriteLine(numbers[0]); // 10
// 部分屬性
public partial class Person
{
public partial string Name { get; set; }
}
public partial class Person
{
public partial string Name { get => _name; set => _name = value; }
private string _name;
}
var person = new Person { 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,無需顯式聲明。
示例代碼
public class Person
{
public string Name
{
get => field;
set => field = value?.Trim();
}
}
var person = new Person { 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 = new int[] {1, 2, 3};
int[] array = span.ToArray();
Console.WriteLine(string.Join(", ", array)); // 1, 2, 3
適用場景
-
高性能場景中,減少顯式轉換。 -
與數組和 span 類型交互。
注意事項
-
需確保 span 的生命周期管理,詳見Span 轉換。
nameof 支持未綁定泛型
概述
允許 nameof 操作符使用未綁定泛型類型。
示例代碼
string listName = nameof(List<>);
Console.WriteLine(listName); // List
適用場景
-
泛型編程中,獲取類型名稱。
注意事項
-
簡單但強大的增強,適合反射場景。
lambda 參數修飾符
概述
允許在 lambda 表達式中為參數添加修飾符,如 ref、out 等,無需指定類型。
示例代碼
var increment = (ref int x) => x++;
int num = 5;
increment(ref num);
Console.WriteLine(num); // 6
適用場景
-
需要在 lambda 中修改外部變量。
注意事項
-
params仍需指定類型,詳見lambda 表達式。
partial 構造函數和事件
概述
擴展 partial 成員到實例構造函數和事件,允許在 partial 類型中分離定義和實現。
示例代碼
// File1.cs
public partial class MyClass
{
public partial MyClass(int x);
public partial event EventHandler MyEvent;
}
// File2.cs
public partial class MyClass
{
public partial MyClass(int x) { }
public partial event EventHandler MyEvent;
}
適用場景
-
代碼生成場景,如 UI 設計器。
注意事項
-
需確保 defining 和 implementing 聲明一致,詳見partial 成員。
空條件賦值
概述
允許在賦值語句的左側使用 ?. 和 ?[],僅當左側非 null 時執行賦值。
示例代碼
string? text = null;
text?.Length = 5; // 不執行賦值
List<int>? list = null;
list?[0] = 10; // 不執行賦值
list = new List<int> { 0 };
list?[0] = 10; // 執行賦值,list[0] = 10
Console.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以獲取最新更新。
本文來自博客園,作者:AI·NET極客圈,轉載請注明原文鏈接:http://www.rzrgm.cn/code-daily/p/18844112
歡迎關注我們的公眾號,作為.NET工程師,我們聚焦人工智能技術,探討 AI 的前沿應用與發展趨勢,為你立體呈現人工智能的無限可能,讓我們共同攜手共同進步。

浙公網安備 33010602011771號