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

В C# 10 добавлены следующие функции и улучшения языка C#:

C# 10 поддерживается в .NET 6. Дополнительные сведения см. в статье Управление версиями языка C#.

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

Примечание.

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

Структуры записей

Вы можете объявлять записи типа значения с помощью объявления record structreadonly record struct или . Теперь путем объявления record class вы можете уточнить, что record имеет ссылочный тип.

Улучшения типов структуры

В C# 10 реализованы следующие улучшения, связанные с типами структур:

Обработчик интерполированных строк

Можно создать тип, который создает результирующую строку на основе выражения интерполированной строки. Библиотеки .NET используют эту функцию во многих интерфейсах API. Вы можете создать такой обработчик, следуя инструкциям из этого руководства.

Глобальные директивы using

Можно добавить модификатор global в любую директиву using, чтобы указать компилятору, что эта директива применяется ко всем исходным файлам в компиляции. Обычно это все исходные файлы в проекте.

Объявление пространства имен в пределах файла

Можно использовать новую форму объявления namespace, чтобы объявить, что все последующие объявления являются членами объявленного пространства имен:

namespace MyNamespace;

Этот новый синтаксис сохраняет как горизонтальное, так и вертикальное пространство для объявлений namespace.

Расширенные шаблоны свойств

Начиная с C# 10 можно ссылаться на вложенные свойства или поля в шаблоне свойства. Например, шаблон формы

{ Prop1.Prop2: pattern }

допустим в C# 10 и более поздних версиях и эквивалентен

{ Prop1: { Prop2: pattern } }

допустим в C# 8.0 и более поздних версиях.

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

Улучшения лямбда-выражений

В C# 10 включено множество улучшений обработки лямбда-выражений:

  • Лямбда-выражения могут иметь естественный тип, где компилятор может вывести тип делегата из лямбда-выражения или группы методов.
  • Лямбда-выражения могут объявлять тип возвращаемого значения, если компилятор не может его вывести.
  • К лямбда-выражениям могут применяться атрибуты.

Эти функции делают лямбда-выражения более похожими на методы и локальные функции. Они упрощают использование лямбда-выражений без объявления переменной типа делегата и более тесно работают с новыми минимальными API ASP.NET Core.

Константные интерполированные строки

В C# 10 строки const могут быть инициализированы с помощью интерполяции строк, если все заполнители являются константными строками. Интерполяция строк упрощает чтение константных строк при их создании в приложении. Выражения заполнителей не могут быть числовыми константами, так как эти константы преобразуются в строки во время выполнения. Текущий язык и региональные параметры могут влиять на строковое представление. Дополнительные сведения см. в справочнике по языку для выражений const.

Типы записей могут запечатывать ToString

В C# 10 можно добавить модификатор sealed при переопределении ToString в типе записи. Запечатывание метода ToString предотвращает синтезирование компилятором метода ToString для любых производных типов записей. A sealedToString гарантирует, что все производные типы записей используют метод, ToString определенный в общем базовом типе записей. Дополнительные сведения об этой функции см. в статье о записях.

Присваивание и объявление в одном и том же деконструировании

Это изменение снимает ограничение, существовавшее в предыдущих версиях C#. Ранее деконструирование могло присвоить все значения существующим переменным или инициализировать только что объявленные переменные:

// Initialization:
(int x, int y) = point;

// assignment:
int x1 = 0;
int y1 = 0;
(x1, y1) = point;

C# 10 устраняет это ограничение:

int x = 0;
(x, int y) = point;

Улучшенное определенное назначение

До C# 10 существовало много сценариев, в которых при определенном назначении и анализе состояния NULL возникали ложноположительные предупреждения. Обычно они были связаны со сравнениями с логическими константами, доступом к переменной только в операторах true или false в операторе if и выражениях объединения со значением NULL. Эти примеры создавали предупреждения в предыдущих версиях C#, но не в C# 10:

string representation = "N/A";
if ((c != null && c.GetDependentValue(out object obj)) == true)
{
   representation = obj.ToString(); // undesired error
}

// Or, using ?.
if (c?.GetDependentValue(out object obj) == true)
{
   representation = obj.ToString(); // undesired error
}

// Or, using ??
if (c?.GetDependentValue(out object obj) ?? false)
{
   representation = obj.ToString(); // undesired error
}

Основное преимущество этого улучшения состоит в том, что предупреждения для определенного назначения и анализа состояния NULL теперь являются более точными.

Разрешен атрибут AsyncMethodBuilder в методах

В C# 10 и последующих версиях можно указать другой построитель асинхронных методов для одного метода в дополнение к указанию типа построителя методов для всех методов, возвращающих данный тип, аналогичный задаче. Построитель пользовательских асинхронных методов предоставляет больше возможностей для настройки производительности в сценариях, когда определенный метод может выиграть от настраиваемого построителя.

Дополнительные сведения см. в разделе AsyncMethodBuilder статьи об атрибутах, считываемых компилятором.

Диагностика атрибута CallerArgumentExpression

Можно использовать System.Runtime.CompilerServices.CallerArgumentExpressionAttribute, чтобы указать параметр, который компилятор заменяет текстовым представлением другого аргумента. Эта функция позволяет библиотекам создавать более конкретные диагностические сведения. Следующий код проверяет условие. Если условие имеет значение false, сообщение об исключении содержит текстовое представление аргумента, переданного в condition:

public static void Validate(bool condition, [CallerArgumentExpression("condition")] string? message=null)
{
    if (!condition)
    {
        throw new InvalidOperationException($"Argument failed validation: <{message}>");
    }
}

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

Улучшенная прагма #line

C# 10 поддерживает новый формат для прагмы #line. Скорее всего, вы не будете использовать новый формат, но заметите его влияние. Улучшения обеспечивают более детализированные выходные данные в предметно-ориентированных языках (DSL), например Razor. Подсистема Razor использует эти усовершенствования для улучшения процесса отладки. Отладчики смогут точнее выделять источник Razor. Дополнительные сведения о новом синтаксисе см. в статье о директивах препроцессора в справочнике по языку. Также можно прочитать спецификацию функции, чтобы найти примеры для Razor.