Поделиться через


Новые возможности C# 14

C# 14 включает следующие новые функции. Эти функции можно попробовать с помощью последней версии Visual Studio 2026 или пакета SDK для .NET 10:

C# 14 — это последний выпуск C#. C# 14 поддерживается в .NET 10. Дополнительные сведения см. в разделе версии языка C# .

Скачать последний пакет SDK для .NET 10 можно на странице скачивания .NET. Вы также можете скачать Visual Studio 2026, который включает пакет SDK для .NET 10.

Критические изменения, внесенные в C# 14, можно найти в нашей статье о критических изменениях.

Примечание.

Мы заинтересованы в ваших отзывах об этих функциях. Если вы найдете проблемы с любым из этих новых функций, создайте новую проблему в репозитории dotnet/roslyn.

Члены расширения

C# 14 добавляет новый синтаксис для определения элементов расширения. Новый синтаксис позволяет объявлять свойства расширения в дополнение к методам расширения. Можно также объявить члены расширения, которые расширяют сам тип, а не экземпляры этого типа. Другими словами, эти новые члены расширения могут отображаться как статические элементы расширенного типа. Эти расширения могут включать определяемые пользователем операторы, реализованные как статические методы расширения. В следующем примере кода показан пример различных типов элементов расширения, которые можно объявить:

public static class Enumerable
{
    // Extension block
    extension<TSource>(IEnumerable<TSource> source) // extension members for IEnumerable<TSource>
    {
        // Extension property:
        public bool IsEmpty => !source.Any();

        // Extension method:
        public IEnumerable<TSource> Where(Func<TSource, bool> predicate) { ... }
    }

    // extension block, with a receiver type only
    extension<TSource>(IEnumerable<TSource>) // static extension members for IEnumerable<Source>
    {
        // static extension method:
        public static IEnumerable<TSource> Combine(IEnumerable<TSource> first, IEnumerable<TSource> second) { ... }

        // 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);
    }
}

Элементы в первом блоке расширения вызываются так, как будто они являются членами экземпляра IEnumerable<TSource>, например sequence.IsEmpty. Элементы во втором блоке расширения вызываются так, как будто они являются статическими элементами IEnumerable<TSource>, например IEnumerable<int>.Identity.

Дополнительные сведения см. в статье о членах расширений в руководстве по программированию, справочной статье extensionпо языку ключевого слова и спецификации компонентов для новых элементов расширения.

Ключевое слово field

Токен field позволяет вам написать тело доступа к свойству, не объявляя явное поле для хранения данных. Маркер field заменяется на поле синтезированной резервной копии компилятора.

Например, ранее, если вы хотели убедиться, что свойство string не может быть установлено в null, вам нужно было объявить резервное поле и реализовать оба аксессора.

private string _msg;
public string Message
{
    get => _msg;
    set => _msg = value ?? throw new ArgumentNullException(nameof(value));
}

Теперь вы можете упростить код следующим образом:

public string Message
{
    get;
    set => field = value ?? throw new ArgumentNullException(nameof(value));
}

Вы можете определить тело для одного или обоих акцессоров свойства, связанного с полем.

Возможны существенные изменения или путаница при чтении кода в типах, которые также содержат символ с именем field. Вы можете использовать @field или this.field, чтобы разрешить неоднозначность между field ключевым словом и идентификатором, или переименовать текущий field символ, чтобы обеспечить чёткое различие.

Неявные преобразования диапазона

C# 14 предоставляет первоклассную поддержку для System.Span<T> и System.ReadOnlySpan<T> в языке. Эта поддержка включает новые неявные преобразования, позволяющие более естественное программирование с этими типами.

Span<T> и ReadOnlySpan<T> используются различными ключевыми способами в C# и среде выполнения. Их введение повышает производительность без риска безопасности. C# 14 распознает связь и поддерживает некоторые преобразования между ReadOnlySpan<T>, Span<T>и T[]. Типы span могут выступать в качестве получателей методов расширения, комбинироваться с другими преобразованиями и помогать в ситуациях вывода универсальных типов.

Список неявных преобразований диапазона можно найти в статье о встроенных типах в разделе справочника по языку. Дополнительные сведения см. в спецификации функции для типов диапазонов первого класса.

Несвязанные обобщенные типы и nameof

Начиная с C# 14 аргумент nameof может быть несвязанным универсальным типом. Например, nameof(List<>) принимает значение List. В более ранних версиях C# для возврата List<int> имени можно использовать только закрытые универсальные типы, напримерList.

Простые лямбда-параметры с модификаторами

Модификаторы параметров, например scoped, , ref, inoutили ref readonly лямбда-выражения, можно добавить без указания типа параметра:

delegate bool TryParse<T>(string text, out T result);
// ...
TryParse<int> parse1 = (text, out result) => Int32.TryParse(text, out result);

Ранее добавление модификаторов было разрешено только в том случае, если объявления параметров включали типы параметров. В предыдущем объявлении требуется указывать типы для всех параметров.

TryParse<int> parse2 = (string text, out int result) => Int32.TryParse(text, out result);

Модификатор params по-прежнему требует явно типизированного списка параметров.

Дополнительные сведения об этих изменениях см. в статье об лямбда-выражениях в справочнике по языку C#.

Частично задействованные члены

Теперь вы можете объявлять конструкторы экземпляра и события как частичные элементы.

Частичные конструкторы и частичные события должны включать ровно одно определение объявления и одно реализующее объявление.

Только реализующее объявление частичного конструктора может включать инициализатор конструктора: this() или base(). Только одно объявление частичного типа может включать синтаксис основного конструктора.

Объявление реализации частичного события должно включать аксессоры add и remove. Определяющее объявление декларирует событие, похоже на поле.

Определяемое пользователем составное назначение

Подробнее см. в спецификации функции для пользовательского составного присваивания.

null-условное присваивание

Операторы условного доступа к члену ?. и ?[] теперь можно использовать на левой стороне назначения или составного назначения.

До C# 14 необходимо было проверять переменную на null, прежде чем присваивать значение свойству.

if (customer is not null)
{
    customer.Order = GetCurrentOrder();
}

Вы можете упростить предыдущий код, используя оператор ?..

customer?.Order = GetCurrentOrder();

Правая сторона оператора вычисляется только в том случае, если левая сторона = не имеет значения NULL. Если customer является null, код не вызывает GetCurrentOrder.

В дополнение к назначению можно использовать операторы доступа к условному члену NULL с составными операторами назначения (+=, -=и другими). Однако инкремент и декремент, ++ и --, не разрешены.

Дополнительные сведения см. в справочной статье по языку о доступе к условному члену и спецификации компонентов для условного назначения null.

См. также