Exploring C# 14: New Features and Enhancements

C# 14, released with .NET 10, introduces several exciting features that enhance performance, simplify code, and improve developer productivity. This blog post dives into the key changes and additions in C# 14, based on the official documentation from Microsoft Learn. Let’s explore what’s new and how these features can elevate your C# programming experience.

1. First-Class Support for Span<T> and ReadOnlySpan<T>

C# 14 brings robust support for System.Span<T> and System.ReadOnlySpan<T>, making it easier to work with these high-performance types. These span types are critical for optimizing memory usage and performance in scenarios like string manipulation, array slicing, and buffer management.

What’s New?

  • Implicit Conversions: C# 14 introduces implicit conversions between Span<T>, ReadOnlySpan<T>, and T[], allowing more natural and flexible coding patterns.
  • Extension Method Receivers: Span<T> and ReadOnlySpan<T> can now act as receivers for extension methods, enabling cleaner and more reusable code.
  • Improved Type Inference: The compiler now better handles generic type inference involving spans, reducing the need for explicit type annotations.
  • Composability: Span conversions can compose with other implicit conversions, making complex operations more seamless.

Example

// Converting an array to a Span<T> and using it in an extension method
string[] words = ["Hello", "World"];
ReadOnlySpan<string> span = words;
span.Print(); // Assuming Print is an extension method for ReadOnlySpan<string>

Why It Matters?

These enhancements make Span<T> and ReadOnlySpan<T> more intuitive to use, improving performance without sacrificing safety. Developers can write more efficient code for memory-intensive operations, especially in high-performance applications like game development or real-time data processing.

2. Token Field for Properties (field Keyword)

The field keyword, introduced as a preview in C# 13, is now fully supported in C# 14. It simplifies property declarations by eliminating the need to explicitly declare a backing field.

What’s New?

  • Simplified Property Syntax: The field keyword allows you to write property accessors that automatically use a compiler-synthesized backing field.
  • Null-Checking Made Easy: You can implement custom logic, like null checks, directly in the property setter without managing a backing field manually.
  • Disambiguation: To avoid conflicts with a field named field, you can use @field or this.field for clarity.

Example

public class MessageHandler
{
    // Old way (C# 13 and earlier)
    private string _msg;
    public string Message
    {
        get => _msg;
        set => _msg = value ?? throw new ArgumentNullException(nameof(value));
    }

    // New way in C# 14
    public string NewMessage
    {
        get;
        set => field = value ?? throw new ArgumentNullException(nameof(value));
    }
}

Why It Matters?

The field keyword reduces boilerplate code, making property declarations more concise and readable. It’s particularly useful for validation logic in setters, streamlining code maintenance.

Note. Be cautious when using the field keyword in classes with a field named field, as it may shadow the existing field. Use @field or rename the field to avoid confusion.

3. Null-Conditional Member Access for Assignments

C# 14 extends the null-conditional operators (?. and ?[]) to support assignments and compound assignments, simplifying null-checking logic.

What’s New?

  • Assignment with ?.: You can now use the null-conditional operator on the left-hand side of an assignment. The right-hand side is evaluated only if the left-hand side is non-null.
  • Compound Assignments: Operators like +=, -=, etc., are supported with null-conditional access.
  • Limitations: Increment (++) and decrement (--) operators are not supported.

Example

public class OrderProcessor
{
    public Customer? Customer { get; set; }

    public void UpdateOrder()
    {
        // Old way (C# 13 and earlier)
        if (Customer != null)
        {
            Customer.Order = GetCurrentOrder();
        }

        // New way in C# 14
        Customer?.Order = GetCurrentOrder(); // Only assigns if Customer is not null
    }

    private Order GetCurrentOrder() => new Order();
}

Why It Matters?

This feature reduces verbose null checks, making code more concise and less error-prone. It’s particularly useful in scenarios involving nested object hierarchies or optional data.

4. Extension Members (Preview Feature)

C# 14 introduces extension members as a preview feature, expanding the capabilities of extension methods to include properties and static members.

What’s New?

  • Extension Properties: You can now define extension properties, allowing you to add computed properties to existing types without modifying them.
  • Static Extension Members: Extension types can include static methods and properties, enabling more flexible designs.
  • Usage: Declared using the extension keyword, these members are currently in preview and require Visual Studio 2022 version 17.14 or later.

Example

// Extension property for counting words in a string
public extension StringExtensions for string
{
    public int WordCount => this.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
}

string text = "Hello C# 14 World";
Console.WriteLine(text.WordCount); // Outputs: 4

Why It Matters?

Extension members make it easier to add functionality to existing types, promoting code reuse and cleaner APIs. This is especially valuable for library authors and developers working with immutable or third-party types.

Note. As a preview feature, extension members may evolve before their final release. Provide feedback via the dotnet/roslyn repository.

5. Breaking Changes and Considerations

C# 14 introduces some breaking changes that may affect existing code.

  • Span Conversion Overloads: New span conversions may cause the compiler to select different overloads compared to C# 13, potentially leading to ambiguity errors or runtime issues like ArrayTypeMismatchException. Workarounds include explicitly casting to AsSpan() or using OverloadResolutionPriorityAttribute.
  • Lambda Parameter Modifiers: The scoped keyword is now always treated as a modifier in lambda parameters, which may break code using scoped as a type name. Use @scoped for type names as a workaround.
  • Partial Events and Constructors: The partial modifier’s expanded usage may conflict with types named partial. Use @partial to escape the keyword.

For a full list of breaking changes, refer to the C# compiler breaking changes documentation.

Getting Started with C# 14

To try C# 14, you’ll need.

  • .NET 10 SDK: Download from the .NET downloads page.
  • Visual Studio 2022 (version 17.14 or later): Includes the .NET 10 SDK and supports C# 14 features.
  • Project Configuration: Set <LangVersion>14</LangVersion> in your .csproj file to enable C# 14 features. For preview features like extension members, use <LangVersion>preview</LangVersion>.

Share Your Feedback

The C# team encourages developers to provide feedback on these features. If you encounter issues or have suggestions, create an issue in the dotnet/roslyn or csharplang repositories on GitHub.

Conclusion

C# 14 builds on the language’s tradition of balancing performance, safety, and developer productivity. With first-class support for spans, the field keyword, null-conditional assignments, and the preview of extension members, C# 14 empowers developers to write cleaner, more efficient code. Whether you’re building high-performance applications or simplifying everyday tasks, these features offer practical benefits.

Explore C# 14 today and let us know how these changes enhance your development workflow.

Source: What’s new in C# 14 | Microsoft Learn