Location>code7788 >text

C# high-performance development type systems: panoramic perspective of type systems evolution from C# 7.0 to C# 14

Popularity:178 ℃/2025-04-24 10:19:38

Since C# 7.0, C# language has introduced many new data types, type constructs and language features in type systems to improve performance, type safety and development efficiency. This article comprehensively compiles new content from C# 7.0 to C# 14.0 (as of April 2025, C# 14.0 is the preview version), including value tuples,Span<T>ReadOnlySpan<T>Memory<T>ReadOnlyMemory<T>, nullable reference types, records, native size integers, record structures, inline arrays, and other enhancements (such as read-only structures, generic math support).

Version Overview

The following are the main contents of the type system added or enhanced in C# 7.0 to C# 14.0:

C# version Added/enhanced content Release year describe
7.0 Value Tuples 2017 Lightweight data structure, supporting multi-value return and destructuring
7.2 Span, ReadOnlySpan, read-only structure, reference structure 2017 High-performance memory operation and immutable/stack allocation structure
8.0 Nullable reference type, Memory, ReadOnlyMemory 2019 Null value security and managed memory blocks
9.0 Record, native size integer, initializer-specific type 2020 Value semantic reference types, native integers, and immutable properties
10.0 Record structure, global using directive 2021 Value type records and simplified type references
11.0 Required members, generic math support, file local types 2022 Forced initialization, generic operations, and type scope limitations
12.0 Inline arrays 2023 Fixed-size array structure, optimize performance
13.0 Parameter collection extension, reference structure interface support, some attributes 2024 Extend params, ref struct interface and partial property definitions
14.0 fieldkeywords, implicit span conversion,nameofEnhancement, lambda parameter modifier, partial member extension, empty condition assignment 2025 Enhanced attribute access, span usage, generic processing, lambda expression, partial type, and null value processing

The following is detailed by version, each section contains feature tables, code examples, and analysis.

C# 7.0: Value Tuples

Feature Table

Type/Construction describe Main uses Things to note
Value Tuples Lightweight value type, supports multi-value return, named elements and deconstruction Method returns multiple values ​​and temporary data grouping Value type, stack allocation; .NET Framework requires reference packages

Overview

Value tuples are based on, allows methods to return multiple values, supports named elements and deconstruction, and simplifies data transfer.

grammar

  • statement:(type1, type2, ...) tupleName = (value1, value2, ...);
  • Named elements:(type1 name1, type2 name2, ...) tupleName = (value1, value2, ...);
  • Deconstruction:var (var1, var2, ...) = tupleName;

Sample code

public (int id, string name) GetPerson()
 {
 return (1, "Alice");
 }

 var person = GetPerson();
 ($"ID: {}, Name: {}");

 // Deconstruction
 var (id, name) = GetPerson();
 ($"ID: {id}, Name: {name}");

Applicable scenarios

  • The method returns multiple related values.
  • Temporary data grouping without defining classes or structures.
  • Deconstruct assignments and simplify the code.

Things to note

  • Value type, suitable for lightweight data.
  • The .NET Framework project requires reference to the NuGet package.

C# 7.2: Span, ReadOnlySpan, read-only structure, reference structure

Feature Table

Type/Construction describe Main uses Things to note
Span Refers to continuous memory blocks, supporting read and write High-performance array/memory operation ref struct, stack allocation, life cycle limit
ReadOnlySpan Read-only continuous memory block reference High-performance read-only operation Same as above, memory boundary security needs to be ensured
Readonly struct Immutable structure, optimize performance Immutable data structure All instance fields must be read only
Reference structure (ref struct) Stack allocation structure High-performance memory management Can't box or implement as an interface

Overview

Span<T>andReadOnlySpan<T>is a high-performance value type that represents continuous memory block references, suitable for array and native memory operations.readonly structEnsure that the structure is immutable,ref structLimit to stack allocation, supportSpan<T>etc.

grammar

  • Span: Span<T> span = ();
  • ReadOnlySpan: ReadOnlySpan<T> readOnlySpan = ();
  • Read-only structure:readonly struct StructName { ... }
  • Quote Structure:ref struct StructName { ... }

Sample code

// Span<T>  and ReadOnlySpan<T>
 int[] numbers = [1, 2, 3, 4, 5];
 Span<int> span = (1, 3);
 span[0] = 10;
 ((", ", ())); // 10, 3, 4

 ReadOnlySpan<char> text = "Hello".AsSpan();
 ((0, 2).ToString()); // He

 // Read-only structure
 readonly struct Point
 {
 public int X { get; init; }
 public int Y { get; init; }
 }
 Point point = new() { X = 1, Y = 2 };
 ($"({}, {})"); // (1, 2)

 // Quote Structure
 ref struct  Buffer
 {
 public Span<int> Data;
 public Buffer(Span<int> data) => Data = data;
 }
 Buffer buffer = new(());
 [0] = 10;
 (numbers[0]); // 10

Applicable scenarios

  • High-performance string parsing and buffer processing.
  • Immutable data structure (read-only structure).
  • Avoid heap allocation (reference structure).

Things to note

  • Span<T>andReadOnlySpan<T>Not available for asynchronous methods.
  • ref structStrict restrictions and need to manage life cycles.

C# 8.0: Nullable reference types, Memory, ReadOnlyMemory

Feature Table

Type/Construction describe Main uses Things to note
Nullable reference type Reference types can be marked as nullable, default is not null Enhanced null value security Need to enable nullable context to handle compiler warnings
Memory Hosted memory blocks, support reading and writing Asynchronous and high-performance memory operations Suitable for asynchronous scenarios, and requires management of life cycles
ReadOnlyMemory Read-only managed memory blocks Read-only asynchronous memory operation Same as above

Overview

The nullable reference type passes?The suffix specifies whether the reference type can be null, reducing null reference exceptions.Memory<T>andReadOnlyMemory<T>Represents a managed memory block and supports asynchronous scenarios.

grammar

  • Nullable reference type:string? nullable; string nonNullable;
  • Memory: Memory<T> memory = ();
  • ReadOnlyMemory: ReadOnlyMemory<T> readOnlyMemory = ();

Sample code

// nullable reference type
 #nullable enable
 string nonNullable = "Hello";
 string? nullable = null;
 if (nullable != null)
 {
 ();
 }

 // Memory<T>  and ReadOnlyMemory<T>
 int[] numbers = [1, 2, 3, 4, 5];
 Memory<int> memory = (1, 3);
 Span<int> span = ;
 span[0] = 10;
 ((", ", ())); // 10, 3, 4

 ReadOnlyMemory<char> text= "Hello".AsMemory();
 ((0, 2).()); // He

Applicable scenarios

  • Enhanced null value security (nullable reference type).
  • Asynchronous memory operation (Memory).
  • ReadOnlyMemory.

Things to note

  • The nullable reference type needs to be enabled explicitly.
  • Memory life cycle needs to be managed.

C# 9.0: Record, native size integer, initializer-specific type

Feature Table

Type/Construction describe Main uses Things to note
Records Reference type with value semantics, default immutable Data modeling, value equality Immutable by default, variable behavior can be added
Native size integer (nint, nuint) Native size integer, map IntPtr/UIntPtr Native code interoperability Platform dependencies need to be considered
Init-only setters Immutable properties after initialization Immutable data model Only assign values ​​during initialization

Overview

Records are reference types with value semantics, and equality is automatically achieved.nintandnuintSupports native size integers.initModifiers enhance attribute immutability.

grammar

  • Record:public record ClassName(type1 Property1, ...);
  • Native size integer:nint nativeInt; nuint nativeUInt;
  • init-only: public type Property { get; init; }

Sample code

// Record
 public record Person(string FirstName, string LastName);
 var person1 = new Person("Alice", "Smith");
 var person2 = new Person("Alice", "Smith");
 (person1 == person2); // True
 var person3 = person1 with { LastName = "Johnson" };
 (person3); // Person { FirstName = Alice, LastName = Johnson }

 //Native size integer
 nint nativeInt = 42;
 nuint nativeUInt = 42u;
 ($"Native int: {nativeInt}, Native uint: {nativeUInt}");

 // Special type for initializer
 public class Student
 {
 public string Name { get; init; }
 }
 var student = new Student { Name = "Alice" };
 (); // Alice

Applicable scenarios

  • Data transfer object (record).
  • Native code interoperability (nint, nuint).
  • Immutable data model (init-only).

Things to note

  • Records support inheritance and must maintain value semantics.
  • Native size integer platform dependencies.

C# 10.0: Record structure, global using directive

Feature Table

Type/Construction describe Main uses Things to note
Record Structs Recording of value types, combining value semantics and performance Small data structure Value type, copy cost needs to be considered
Global using command Global import namespace Simplify type references Need to balance code readability

Overview

Record structures extend record characteristics to value types, combining value semantics and performance. GlobalusingSimplify type references.

grammar

  • Record structure:public record struct StructName(type1 Property1, ...);
  • Global using:global using System;

Sample code

// Record structure
 public record struct Point(int X, int Y);
 var point1 = new Point(1, 2);
 var point2 = new Point(1, 2);
 (point1 == point2); // True
 var point3 = point1 with { X = 3 };
 (point3); // Point { X = 3, Y = 2}

 // Global using (assuming it is already at the top of the file)
 ("Hello, World!"); // No need to use System explicitly

Applicable scenarios

  • Value type data modeling (record structure).
  • Large project namespace management (global using).

Things to note

  • The cost of copying the record structure needs to be paid attention to.
  • Global using should be used with caution.

C# 11.0: Required Members, Generic Mathematical Support, File Local Types

Feature Table

Type/Construction describe Main uses Things to note
Required members Force member initialization Ensure the key fields are initialized Need to be combined with the initializer or constructor
Generic Mathematics Support Static abstract interface members support generic operations Generic Algorithm Library Requires runtime support (.NET 7+)
File local type (file modifyer) Restrict type scope to file Isolation Assistance Type File scope only

Overview

requiredModifier forces member initialization. Generic mathematics supports numerical operations through interfaces.fileModifiers limit type scope.

grammar

  • Required Members:public required type Property { get; set; }
  • Generic Mathematics:interface INumber<T> { static abstract T operator +(T, T); }
  • File local type:file class ClassName { ... }

Sample code

// Required Member
 public class Person
 {
 public required string Name { get; set; }
 }
 var person = new Person { Name = "Alice" };
 (); // Alice

 // Generic Math Support
 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( + );
 }
 MyNumber a = new(1);
 MyNumber b = new(2);
 var result = (a, b);
 (); // 3

 // File local type
 file class Helper
 {
 public static void Log(string message) => (message);
 }
 ("Test");

Applicable scenarios

  • API design (required members).
  • Generic numerical calculation (generic mathematics).
  • Code generation (file local type).

Things to note

  • Required members need to be explicitly initialized.
  • Generic mathematics requires runtime support.

C# 12.0: Inline Arrays

Feature Table

Type/Construction describe Main uses Things to note
Inline Arrays Fixed-size array structure, stack allocation High performance fixed-size arrays Fixed size, only within the structure

Overview

Inline array through[InlineArray]Features define fixed-size array structures to optimize performance.

grammar

[InlineArray(length)]
public struct StructName
{
    private elementType _element0;
}

Sample code

[InlineArray(10)]
public struct Buffer
{
    private int _element0;
}
Buffer buffer = new();
buffer[0] = 1;
buffer[9] = 10;
(buffer[0]); // 1

Applicable scenarios

  • High performance computing.
  • Replaces unsafe fixed buffers.

Things to note

  • Fixed size, not adjustable during runtime.

C# 13.0: Parameter collection extension, reference structure interface support, some attributes

Feature Table

Type/Construction describe Main uses Things to note
Parameter set extension (params Span, etc.) Extended params support Span, etc. High performance parameter transfer Span life cycle needs to be ensured
Reference structure interface support Allow ref struct to implement interfaces Extend ref struct capability Still subject to ref struct restrictions
Partial properties Support partial attributes of partial type Code generation Make sure that the definition is consistent

Overview

Parameter collection extension supportSpan<T>etc.ref structInterfaces can be implemented. Some properties support sub-file definitions.

grammar

  • Parameter set:void Method(params Span<T> spans);
  • Reference structure interface:ref struct StructName : IInterface { ... }
  • Some properties:public partial type Property { get; set; }

Sample code

// Parameter set extension
 public void Process(params Span<int> spans)
 {
 foreach (var span in spans)
 ((", ", ()));
 }
 int[] numbers = [1, 2, 3];
 Process((0, 2), (2, 1)); // 1, 2 and 3

 // Reference structure interface support
 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[0]); // 10

 // Some attributes
 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" };
 (); // Alice

Applicable scenarios

  • High performance parameter transfer (parameter set).
  • Extendedref struct(Interface support).
  • Code generation (partial properties).

Things to note

  • Parameter collections need to manage the Span life cycle.
  • Some attributes need to be consistent.

C# 14.0:fieldkeywords, implicit span conversion,nameofEnhancement, lambda parameter modifier, partial member extension, empty condition assignment

Feature Table

Type/Construction describe Main uses Things to note
fieldKeywords Allow direct access to the backing field in the property accessor Simplify property implementation It may conflict with existing field names and must be used@fieldordistinguish
Implicit span conversion supportSpan<T>ReadOnlySpan<T>Implicit conversion to arrays Use span types more naturally Pay attention to the life cycle of span
nameofSupport unbound generics allownameofUse unbound generic types, such asnameof(List<>) Get type name in generic programming -
lambda parameter modifier Allow lambda parameters to be usedrefoutetc modifier, no need to specify type Enhance the flexibility of lambda expressions paramsStill need to specify the type
partial constructors and events Extend partial members to instance constructors and events Separate definitions and implementations, suitable for code generation Make sure that defining and implementing statements are consistent
Empty condition assignment Allow to use on the left side of the assignment?.and?[], assign only when the left side is not null Simplify null checking Not supported++and--

Overview

C# 14.0 (expected to be released with .NET 10 in 2025 and previewed as of April 2025) introduces a range of language features designed to improve development efficiency and code readability, includingfieldKeywords, implicit span conversion,nameofEnhancement, lambda parameter modifier, partial member extension, and null condition assignment. Although new data types are not introduced, these features significantly enhance the usage of existing types.

fieldKeywords

Overview

fieldKeywords allow direct access to compiler-generated backing fields in the property accessor without explicit declaration.

Sample code

public class Person
{
    public string Name
    {
        get => field;
        set => field = value?.Trim();
    }
}
var person = new Person { Name = " Alice " };
(); // Alice

Applicable scenarios

  • Simplify property implementation, especially when processing setters are required.

Things to note

  • If the class already has a namefieldfields, need to be used@fieldordistinguish.
  • As a preview feature of C# 13.0, C# 14.0 is officially supported, see the field keyword for details.

Implicit span conversion

Overview

C# 14.0 isSpan<T>andReadOnlySpan<T>Implicit conversion with arrays is provided to make its use more natural.

Sample code

Span<int> span = new int[] {1, 2, 3};
int[] array = ();
((", ", array)); // 1, 2, 3

Applicable scenarios

  • In high-performance scenarios, reduce explicit conversions.
  • Interact with array and span types.

Things to note

  • You need to ensure the life cycle management of the span, see Span conversion for details.

nameofSupport unbound generics

Overview

allownameofThe operator uses unbound generic types.

Sample code

string listName = nameof(List<>);
(listName); // List

Applicable scenarios

  • In generic programming, get the type name.

Things to note

  • Simple but powerful enhancement, suitable for reflective scenes.

lambda parameter modifier

Overview

Allows to add modifiers to parameters in lambda expressions, such asrefoutetc, no need to specify the type.

Sample code

var increment = (ref int x) => x++;
int num = 5;
increment(ref num);
(num); // 6

Applicable scenarios

  • External variables need to be modified in lambda.

Things to note

  • paramsYou still need to specify the type, see the lambda expression for details.

partial constructors and events

Overview

Extend partial members to instance constructors and events, allowing for decoupling of definitions and implementations in partial types.

Sample code

// 
public partial class MyClass
{
    public partial MyClass(int x);
    public partial event EventHandler MyEvent;
}

// 
public partial class MyClass
{
    public partial MyClass(int x) { }
    public partial event EventHandler MyEvent;
}

Applicable scenarios

  • Code generation scenarios, such as UI designer.

Things to note

  • It is necessary to ensure that defining and implementing declarations are consistent, see the partial member for details.

Empty condition assignment

Overview

Allows to use on the left side of the assignment statement?.and?[], only if the left side is not null.

Sample code

string? text = null;
 text?.Length= 5; // No assignment is performed

 List<int>? list = null;
 list?[0]= 10; // No assignment is performed

 list = new List<int> { 0 };
 list?[0] = 10; // Execute assignment, list[0] = 10
 (list[0]); // 10

Applicable scenarios

  • Simplify null checking and avoid NullReferenceException.

Things to note

  • Not supported++and--For operation, see the null condition assignment for details.

Conclusion

The new contents of the type system from C# 7.0 to C# 14.0 cover data types such as value tuples, Span, ReadOnlySpan, Memory, ReadOnlyMemory, nullable reference types, records, native size integers, record structures, inline arrays, etc., as well as read-only structures, reference structures, required members, generic math support and other enhancements. C# 14.0 passedfieldKeywords, implicit span conversion and other features further optimize the usage of existing types. These features meet a wide range of needs from high-performance memory management to type-safe modeling. Senior C# engineers can select types based on the scene, such as using Span to optimize performance and record modeling data. Since C# 14.0 is still in the preview stage, it is recommended to follow dotnet/roslyn for the latest updates.