Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
C# 14 включает следующие новые функции. Эти функции можно попробовать с помощью последней версии Visual Studio 2026 или пакета SDK для .NET 10:
- Члены расширения
- Условное присваивание null
-
nameofподдерживает несвязанные универсальные типы -
Более неявные преобразования для
Span<T>иReadOnlySpan<T> - Модификаторы простых лямбда-параметров
-
fieldподдерживаемые свойства -
partialсобытия и конструкторы - определяемые пользователем операторы составных назначений
- новые директивы препроцессора для приложений на основе файлов
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.