Giới thiệu C# 14 – Những tính năng mới dành cho nhà phát triển

C# 14 chính thức ra mắt cùng với .NET 10. Điểm nhấn lớn nhất là extension members (thành viên mở rộng) hoàn toàn mới, nhưng còn rất nhiều tính năng thú vị khác giúp cuộc sống của bạn với tư cách là nhà phát triển trở nên hiệu quả hơn. Bên cạnh đó, chúng tôi cũng bổ sung những tính năng mới giúp tối ưu hiệu suất mà bạn có thể trải nghiệm trong .NET 10. Hãy cùng khám phá tất cả các tính năng mới trong bài viết này.

Extension Members (Thành viên mở rộng)

Extension members là tính năng nổi bật nhất của C# 14. Cú pháp mới hoàn toàn tương thích với các phương thức mở rộng hiện có. Extension members cho phép bạn tạo extension properties, extension operators và static extension members.

Ví dụ về một extension block:

public static class EnumerableExtensions
{
    // Instance-style extension members: 'source' là biến receiver
    extension<TSource>(IEnumerable<TSource> source)
    {
        // Extension property
        public bool IsEmpty => !source.Any();

        // Extension method
        public IEnumerable<TSource> Where(Func<TSource, bool> predicate)
        {
            throw new NotImplementedException();
        }

        // Static extension property
        public static IEnumerable<TSource> Identity => Enumerable.Empty<TSource>();

        // Static user-defined operator
        public static IEnumerable<TSource> operator +(
            IEnumerable<TSource> left,
            IEnumerable<TSource> right) => left.Concat(right);
    }
}

Cách sử dụng:

int[] data = ...;
// Truy cập instance extension property:
if (data.IsEmpty) { /* ... */ }

// Truy cập static extension operator +
var combined = data + [ 4, 5 ];

// Truy cập static extension property:
var empty = IEnumerable<int>.Identity;

Vì extension blocks tương thích hoàn toàn với các extension methods hiện có, bạn có thể di chuyển từng phương thức một mà không cần biên dịch lại các assembly phụ thuộc.

Tìm hiểu thêm về extension members tại C# Guidetài liệu về từ khóa extension.

Nâng cao năng suất cho bạn

Nhóm tính năng tiếp theo có chung một mục tiêu: giảm thiểu rào cản cú pháp trong các tác vụ hàng ngày để bạn tập trung vào logic nghiệp vụ thay vì các thủ tục rườm rà. Các tính năng này bao gồm:

  • Từ khóa field
  • Unbound generic types và nameof
  • Tham số lambda đơn giản với modifiers
  • Null-conditional assignment
  • Partial events và constructors

Từ khóa field

Hầu hết các thuộc tính (properties) ban đầu đều bắt đầu dưới dạng auto-implemented properties. Sau đó, bạn cần thêm một chút logic nhỏ — kiểm tra null, giới hạn giá trị, chuẩn hóa đơn giản — chỉ trên một accessor. Trước C# 14, điều này buộc bạn phải chuyển sang dạng viết tay hoàn chỉnh với backing field:

// Trước đây
private string _message = "";
public string Message
{
    get => _message;
    init => _message = value 
               ?? throw new ArgumentNullException(nameof(value));
}

Từ khóa ngữ cảnh field tạo ra một bước trung gian: giữ lại sự ngắn gọn của auto-property, chỉ thêm logic tối thiểu khi cần, và để trình biên dịch tự động tạo và đặt tên cho backing storage:

// Sau (C# 14)
public string Message
{
    get; // auto get
    init => field = value 
               ?? throw new ArgumentNullException(nameof(value));
}

Đây là cầu nối giữa auto-implemented và fully hand-written properties. Tính năng này đã có sẵn dưới dạng preview trong .NET 9 và nay đã chính thức trong C# 14.

Unbound generic types và nameof

Trước đây, để log hoặc throw với tên kiểu generic, bạn phải hardcode chuỗi hoặc sử dụng một closed constructed type:

// Trước đây
var listTypeName = nameof(List<int>); // "List"

Giờ đây nameof chấp nhận unbound generic type:

// Sau (C# 14)
var listTypeName = nameof(List<>); // "List"

Tìm hiểu thêm tại tài liệu tham khảo toán tử nameof.

Tham số lambda đơn giản với modifiers

Trong các phiên bản trước, các modifier như out trong delegate yêu cầu khai báo đầy đủ kiểu cho tất cả tham số:

// Trước đây
delegate bool TryParse<T>(string text, out T value);
TryParse<int> parse = (string text, out int result) => int.TryParse(text, out result);

Giờ đây bạn có thể giữ cú pháp ngắn gọn với kiểu ẩn định trong khi vẫn sử dụng các modifiers:

// Sau (C# 14)
TryParse<int> parse = (text, out result) => int.TryParse(text, out result);

Null-conditional assignment

Các phép gán có kiểm tra null trước đây yêu cầu kiểm tra tường minh:

// Trước đây
if (customer is not null)
{
    customer.Order = CreateOrder();
    customer.Total += CalculateIncrement();
}

Giờ đây bạn có thể gán trực tiếp với toán tử null-conditional ở vế trái:

// Sau (C# 14)
customer?.Order = CreateOrder();
customer?.Total += CalculateIncrement();

Xem thêm tại null-conditional assignment.

Partial events và constructors

Các partial type lớn được tạo tự động hoặc sinh mã nguồn giờ có thể phân tán logic event và constructor trên nhiều file:

public partial class Widget(int size, string name)
{
    public partial event EventHandler Changed;
}

public partial class Widget
{
    public partial event EventHandler Changed
    {
        add => _changed += value;
        remove => _changed -= value;
    }

    private EventHandler? _changed;

    public Widget
    {
        Initialize();
    }
}

Xem hướng dẫn về partial constructors.

Hiệu suất tốt hơn cho người dùng của bạn

Nhiều cải thiện về thông lượng xử lý mà bạn thấy sau khi nâng cấp lên .NET 10 đến từ runtime và BCL áp dụng các khả năng mới của C# 14. Các thư viện cốt lõi đã sử dụng những tính năng này, vì vậy ứng dụng của bạn thường chạy nhanh hơn ngay cả khi bạn không tự viết cú pháp này. Hai bổ sung ngôn ngữ đặc biệt quan trọng là:

  • Implicit span conversions
  • User-defined compound assignment

Implicit span conversions

Span<T> / ReadOnlySpan<T> là trung tâm của các API không cấp phát bộ nhớ. C# 14 bổ sung chuyển đổi ngầm định giữa mảng, span và read-only span:

// Sau (C# 14)
string line = ReadLine();
ProcessKey(line[..5]);              // substring slice chuyển đổi ngầm định

int[] buffer = GetBuffer();
Accumulate(buffer[..8]);

So với trước đây phải gọi AsSpan hoặc khởi tạo Span tường minh:

// Trước đây
ReadOnlySpan<char> key = line.AsSpan(0, 5);
Span<int> head = new(buffer, 0, 8);

Tìm hiểu thêm tại first-class span types spec.

User-defined compound assignment

Các kiểu số và vector hiệu suất cao thường tích lũy giá trị trong các vòng lặp chặt. C# 14 cho phép bạn khai báo toán tử compound assignment (+=, -=, v.v.) một cách tường minh:

// Sau (C# 14)
BigVector sum = BigVector.Zero;
foreach (var v in values)
{
    sum += v; // gọi operator += do người dùng định nghĩa
}

Định nghĩa cả toán tử binary và compound:

public struct BigVector(float x, float y, float z)
{
    public float X { get; private set => value = field; } = x;
    public float Y { get; private set => value = field; } = y;
    public float Z { get; private set => value = field; } = z;

    public static BigVector operator +(BigVector l, BigVector r)
        => new(l.X + r.X, l.Y + r.Y, l.Z + r.Z);

    public void operator +=(BigVector r)
    {
        X += r.X;
        Y += r.Y;
        Z += r.Z;
    }
}

Xem chi tiết tại bài viết về operator overloading.

Tổng kết

Trên đây là tổng quan nhanh về những gì chúng tôi đã mang đến trong C# 14: extension members mới, nhiều tính năng giúp bạn làm việc hiệu quả hơn, và các cải tiến giúp chương trình C# của bạn chạy tốt hơn. Hãy tải .NET 10 và dùng thử trên ứng dụng của bạn ngay hôm nay!

Chỉ mục