C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景 ...

打印 上一主题 下一主题

主题 2030|帖子 2030|积分 6090

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
自C# 7.0以来,C#语言在类型系统方面引入了众多新数据类型、类型构造和语言特性,以提升性能、类型安全性和开发效率。本文全面整理了从C# 7.0到C# 14.0(停止2025年4月,C# 14.0为预览版)类型系统的新增内容,包括值元组、Span、ReadOnlySpan、Memory、ReadOnlyMemory、可空引用类型、记录、本机大小整数、记录结构、内联数组,以及其他增强(如只读结构、泛型数学支持)。
版本概览

以下是C# 7.0至C# 14.0中类型系统新增或增强的重要内容:
C# 版本新增/增强内容发布年份形貌7.0值元组(Value Tuples)2017轻量级数据结构,支持多值返回和解构7.2Span, ReadOnlySpan, 只读结构, 引用结构2017高性能内存操作和不可变/栈分配结构体8.0可空引用类型, Memory, ReadOnlyMemory2019空值安全性和托管内存块9.0记录, 本机大小整数, 初始化器专用类型2020值语义引用类型、本机整数和不可变属性10.0记录结构, 全局 using 指令2021值类型记录和简化类型引用11.0必需成员, 泛型数学支持, 文件局部类型2022逼迫初始化、泛型运算和类型作用域限制12.0内联数组2023固定大小数组结构,优化性能13.0参数集合扩展, 引用结构接口支持, 部分属性2024扩展params、ref struct接口和部分属性界说14.0field 关键字, 隐式 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;
示例代码
  1. public (int id, string name) GetPerson()
  2. {
  3.     return (1, "Alice");
  4. }

  5. var person = GetPerson();
  6. Console.WriteLine($"ID: {person.id}, Name: {person.name}");

  7. // 解构
  8. var (id, name) = GetPerson();
  9. 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和ReadOnlySpan是高性能值类型,表示连续内存块引用,恰当数组和本机内存操作。readonly struct确保结构体不可变,ref struct限制为栈分配,支持Span等类型。
语法

<ul data-tool="mdnice编辑器" >Span: Span span = collection.AsSpan();
ReadOnlySpan: ReadOnlySpan Data = data;
}
Buffer buffer = new(numbers.AsSpan());
buffer.Data[0] = 10;
Console.WriteLine(numbers[0]); // 10
[/code]适用场景


  • 高性能字符串解析、缓冲区处理。
  • 不可变数据结构(只读结构)。
  • 避免堆分配(引用结构)。
注意事项


  • Span和ReadOnlySpan不可用于异步方法。
  • ref struct限制严格,需管理生命周期。
C# 8.0:可空引用类型, Memory, ReadOnlyMemory

特性表格

类型/构造形貌重要用途注意事项可空引用类型引用类型可标志为可空,默认非null增强空值安全性需启用可空上下文,处理编译器告诫Memory托管内存块,支持读写异步和高性能内存操作恰当异步场景,需管理生命周期ReadOnlyMemory只读托管内存块只读异步内存操作同上概述

可空引用类型通过?后缀指定引用类型是否可为null,淘汰空引用异常。Memory和ReadOnlyMemory表示托管内存块,支持异步场景。
语法


  • 可空引用类型: string? nullable; string nonNullable;
  • Memory: Memory memory = collection.AsMemory();
  • ReadOnlyMemory: ReadOnlyMemory readOnlyMemory = collection.AsMemory();
示例代码
  1. // Span<T> 和 ReadOnlySpan<T>
  2. int[] numbers = [1, 2, 3, 4, 5];
  3. Span<int> span = numbers.AsSpan(1, 3);
  4. span[0] = 10;
  5. Console.WriteLine(string.Join(", ", span.ToArray())); // 10, 3, 4

  6. ReadOnlySpan<char> text = "Hello".AsSpan();
  7. Console.WriteLine(text.Slice(0, 2).ToString()); // He

  8. // 只读结构
  9. readonly struct Point
  10. {
  11.     public int X { get; init; }
  12.     public int Y { get; init; }
  13. }
  14. Point point = new() { X = 1, Y = 2 };
  15. Console.WriteLine($"({point.X}, {point.Y})"); // (1, 2)

  16. // 引用结构
  17. ref struct Buffer
  18. {
  19.     public Span<int> Data;
  20.     public Buffer(Span<int> data) => Data = data;
  21. }
  22. Buffer buffer = new(numbers.AsSpan());
  23. buffer.Data[0] = 10;
  24. Console.WriteLine(numbers[0]); // 10
复制代码
适用场景


  • 增强空值安全性(可空引用类型)。
  • 异步内存操作(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; }
示例代码
  1. // 可空引用类型
  2. #nullable enable
  3. string nonNullable = "Hello";
  4. string? nullable = null;
  5. if (nullable != null)
  6. {
  7.     Console.WriteLine(nullable.Length);
  8. }

  9. // Memory<T> 和 ReadOnlyMemory<T>
  10. int[] numbers = [1, 2, 3, 4, 5];
  11. Memory<int> memory = numbers.AsMemory(1, 3);
  12. Span<int> span = memory.Span;
  13. span[0] = 10;
  14. Console.WriteLine(string.Join(", ", memory.ToArray())); // 10, 3, 4

  15. ReadOnlyMemory<char> text = "Hello".AsMemory();
  16. Console.WriteLine(text.Slice(0, 2).Span.ToString()); // He
复制代码
适用场景


  • 数据传输对象(记录)。
  • 本机代码互操作(nint, nuint)。
  • 不可变数据模型(init-only)。
注意事项


  • 记录支持继承,需保持值语义。
  • 本机大小整数平台依赖。
C# 10.0:记录结构, 全局 using 指令

特性表格

类型/构造形貌重要用途注意事项记录结构 (Record Structs)值类型的记录,联合值语义和性能小型数据结构值类型,复制本钱需考虑全局 using 指令全局导入命名空间简化类型引用需平衡代码可读性概述

记录结构将记录特性扩展到值类型,联合值语义和性能。全局using简化类型引用。
语法


  • 记录结构: public record struct StructName(type1 Property1, ...);
  • 全局 using: global using System;
示例代码
  1. // 记录
  2. public record Person(string FirstName, string LastName);
  3. var person1 = new Person("Alice", "Smith");
  4. var person2 = new Person("Alice", "Smith");
  5. Console.WriteLine(person1 == person2); // True
  6. var person3 = person1 with { LastName = "Johnson" };
  7. Console.WriteLine(person3); // Person { FirstName = Alice, LastName = Johnson }

  8. // 本机大小整数
  9. nint nativeInt = 42;
  10. nuint nativeUInt = 42u;
  11. Console.WriteLine($"Native int: {nativeInt}, Native uint: {nativeUInt}");

  12. // 初始化器专用类型
  13. public class Student
  14. {
  15.     public string Name { get; init; }
  16. }
  17. var student = new Student { Name = "Alice" };
  18. Console.WriteLine(student.Name); // Alice
复制代码
适用场景


  • 值类型数据建模(记录结构)。
  • 大型项目命名空间管理(全局 using)。
注意事项


  • 记录结构复制本钱需关注。
  • 全局 using 需谨慎利用。
C# 11.0:必需成员, 泛型数学支持, 文件局部类型

特性表格

类型/构造形貌重要用途注意事项必需成员 (required members)逼迫成员初始化确保关键字段初始化需配合初始化器或构造函数泛型数学支持静态抽象接口成员支持泛型运算泛型算法库需运行时支持(.NET 7+)文件局部类型 (file modifier)限制类型作用域至文件隔离辅助类型仅限文件作用域概述

required修饰符逼迫成员初始化。泛型数学支持通过接口实现数值运算。file修饰符限制类型作用域。
语法


  • 必需成员: public required type Property { get; set; }
  • 泛型数学: interface INumber { static abstract T operator +(T, T); }
  • 文件局部类型: file class ClassName { ... }
示例代码
  1. // 记录结构
  2. public record struct Point(int X, int Y);
  3. var point1 = new Point(1, 2);
  4. var point2 = new Point(1, 2);
  5. Console.WriteLine(point1 == point2); // True
  6. var point3 = point1 with { X = 3 };
  7. Console.WriteLine(point3); // Point { X = 3, Y = 2 }

  8. // 全局 using(假设已在文件顶部)
  9. Console.WriteLine("Hello, World!"); // 无需显式 using System
复制代码
适用场景


  • API 设计(必需成员)。
  • 泛型数值计算(泛型数学)。
  • 代码生成(文件局部类型)。
注意事项


  • 必需成员需明确初始化。
  • 泛型数学需运行时支持。
C# 12.0:内联数组

特性表格

类型/构造形貌重要用途注意事项内联数组 (Inline Arrays)固定大小数组结构,栈分配高性能固定大小数组固定大小,仅限结构体内概述

内联数组通过[InlineArray]特性界说固定大小数组结构,优化性能。
语法
  1. // 必需成员
  2. public class Person
  3. {
  4.     public required string Name { get; set; }
  5. }
  6. var person = new Person { Name = "Alice" };
  7. Console.WriteLine(person.Name); // Alice

  8. // 泛型数学支持
  9. public interface INumber<T> where T : INumber<T>
  10. {
  11.     static abstract T Add(T left, T right);
  12. }
  13. public readonly struct MyNumber : INumber<MyNumber>
  14. {
  15.     public int Value { get; init; }
  16.     public MyNumber(int value) => Value = value;
  17.     public static MyNumber Add(MyNumber left, MyNumber right) => new(left.Value + right.Value);
  18. }
  19. MyNumber a = new(1);
  20. MyNumber b = new(2);
  21. var result = MyNumber.Add(a, b);
  22. Console.WriteLine(result.Value); // 3

  23. // 文件局部类型
  24. file class Helper
  25. {
  26.     public static void Log(string message) => Console.WriteLine(message);
  27. }
  28. Helper.Log("Test");
复制代码
示例代码
  1. [InlineArray(length)]
  2. public struct StructName
  3. {
  4.     private elementType _element0;
  5. }
复制代码
适用场景


  • 高性能计算。
  • 替代不安全固定缓冲区。
注意事项


  • 固定大小,运行时不可调整。
C# 13.0:参数集合扩展, 引用结构接口支持, 部分属性

特性表格

类型/构造形貌重要用途注意事项参数集合扩展 (params Span等)扩展params支持Span等高性能参数传递需确保Span生命周期引用结构接口支持允许ref struct实现接口扩展ref struct能力仍受ref struct限制部分属性 (partial properties)支持partial类型部分属性代码生成需确保界说一致概述

参数集合扩展支持Span等类型。ref struct可实现接口。部分属性支持分文件界说。
语法


  • 参数集合: void Method(params Span spans);
  • 引用结构接口: ref struct StructName : IInterface { ... }
  • 部分属性: public partial type Property { get; set; }
示例代码
  1. [InlineArray(10)]
  2. public struct Buffer
  3. {
  4.     private int _element0;
  5. }
  6. Buffer buffer = new();
  7. buffer[0] = 1;
  8. buffer[9] = 10;
  9. Console.WriteLine(buffer[0]); // 1
复制代码
适用场景


  • 高性能参数传递(参数集合)。
  • 扩展ref struct(接口支持)。
  • 代码生成(部分属性)。
注意事项


  • 参数集合需管理Span生命周期。
  • 部分属性需确保一致性。
C# 14.0:field 关键字, 隐式 span 转换, nameof 增强, lambda 参数修饰符, partial 成员扩展, 空条件赋值

特性表格

类型/构造形貌重要用途注意事项field 关键字允许在属性访问器中直接访问 backing field简化属性实现大概与现有字段名辩论,需利用 @field 或 this.field 区分隐式 span 转换支持 Span、ReadOnlySpan 与数组间的隐式转换更自然地利用 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,无需显式声明。
示例代码
  1. // 参数集合扩展
  2. public void Process(params Span<int> spans)
  3. {
  4.     foreach (var span in spans)
  5.         Console.WriteLine(string.Join(", ", span.ToArray()));
  6. }
  7. int[] numbers = [1, 2, 3];
  8. Process(numbers.AsSpan(0, 2), numbers.AsSpan(2, 1)); // 1, 2 和 3

  9. // 引用结构接口支持
  10. public interface IBuffer
  11. {
  12.     void Process();
  13. }
  14. ref struct Buffer : IBuffer
  15. {
  16.     public Span<int> Data;
  17.     public Buffer(Span<int> data) => Data = data;
  18.     public void Process() => Data[0] = 10;
  19. }
  20. Buffer buffer = new(numbers.AsSpan());
  21. buffer.Process();
  22. Console.WriteLine(numbers[0]); // 10

  23. // 部分属性
  24. public partial class Person
  25. {
  26.     public partial string Name { get; set; }
  27. }
  28. public partial class Person
  29. {
  30.     public partial string Name { get => _name; set => _name = value; }
  31.     private string _name;
  32. }
  33. var person = new Person { Name = "Alice" };
  34. Console.WriteLine(person.Name); // Alice
复制代码
适用场景


  • 简化属性实现,特别是需要对 setter 进行处理时。
注意事项


  • 如果类中已有名为 field 的字段,需利用 @field 或 this.field 区分。
  • 作为C# 13.0的预览特性,C# 14.0正式支持,详见field 关键字。
隐式 span 转换

概述

C# 14.0 为 Span 和 ReadOnlySpan 提供了与数组的隐式转换,使其利用更加自然。
示例代码
  1. public class Person
  2. {
  3.     public string Name
  4.     {
  5.         get => field;
  6.         set => field = value?.Trim();
  7.     }
  8. }
  9. var person = new Person { Name = " Alice " };
  10. Console.WriteLine(person.Name); // Alice
复制代码
适用场景


  • 高性能场景中,淘汰显式转换。
  • 与数组和 span 类型交互。
注意事项


  • 需确保 span 的生命周期管理,详见Span 转换。
nameof 支持未绑定泛型

概述

允许 nameof 操作符利用未绑定泛型类型。
示例代码
  1. Span<int> span = new int[] {1, 2, 3};
  2. int[] array = span.ToArray();
  3. Console.WriteLine(string.Join(", ", array)); // 1, 2, 3
复制代码
适用场景


  • 泛型编程中,获取类型名称。
注意事项


  • 简单但强大的增强,恰当反射场景。
lambda 参数修饰符

概述

允许在 lambda 表达式中为参数添加修饰符,如 ref、out 等,无需指定类型。
示例代码
  1. string listName = nameof(List<>);
  2. Console.WriteLine(listName); // List
复制代码
适用场景


  • 需要在 lambda 中修改外部变量。
注意事项


  • params 仍需指定类型,详见lambda 表达式。
partial 构造函数和事件

概述

扩展 partial 成员到实例构造函数和事件,允许在 partial 类型中分离界说和实现。
示例代码
  1. var increment = (ref int x) => x++;
  2. int num = 5;
  3. increment(ref num);
  4. Console.WriteLine(num); // 6
复制代码
适用场景


  • 代码生成场景,如 UI 设计器。
注意事项


  • 需确保 defining 和 implementing 声明一致,详见partial 成员。
空条件赋值

概述

允许在赋值语句的左侧利用 ?. 和 ?[],仅当左侧非 null 时执行赋值。
示例代码
  1. // File1.cs
  2. public partial class MyClass
  3. {
  4.     public partial MyClass(int x);
  5.     public partial event EventHandler MyEvent;
  6. }

  7. // File2.cs
  8. public partial class MyClass
  9. {
  10.     public partial MyClass(int x) { }
  11.     public partial event EventHandler MyEvent;
  12. }
复制代码
适用场景


  • 简化 null 查抄,避免 NullReferenceException。
注意事项


  • 不支持 ++ 和 -- 操作,详见空条件赋值。
结语

C# 7.0至C# 14.0的类型系统新增内容涵盖了值元组、Span、ReadOnlySpan、Memory、ReadOnlyMemory、可空引用类型、记录、本机大小整数、记录结构、内联数组等数据类型,以及只读结构、引用结构、必需成员、泛型数学支持等增强。C# 14.0通过field关键字、隐式 span 转换等特性进一步优化了现有类型的用法。这些特性满足了从高性能内存管理到类型安全建模的多种需求。资深C#工程师可根据场景选择类型,如利用Span优化性能,记录建模数据。由于C# 14.0尚在预览阶段,建议关注dotnet/roslyn以获取最新更新。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宝塔山

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表