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

В C# 11 добавлены следующие функции:

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

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

Примечание.

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

Универсальные атрибуты

Можно объявить универсальный класс, базовым классом которого является System.Attribute. Эта функция предоставляет более удобный синтаксис атрибутов, требующих System.Type параметра. Ранее вам пришлось бы создать атрибут, который принимает Type качестве параметра конструктора:

// Before C# 11:
public class TypeAttribute : Attribute
{
   public TypeAttribute(Type t) => ParamType = t;

   public Type ParamType { get; }
}

А для применения атрибута следовало бы использовать оператор typeof:

[TypeAttribute(typeof(string))]
public string Method() => default;

С помощью этой новой функции можно создать универсальный атрибут:

// C# 11 feature:
public class GenericAttribute<T> : Attribute { }

Затем укажите параметр типа для использования атрибута:

[GenericAttribute<string>()]
public string Method() => default;

При применении атрибута необходимо указать всех параметры типа. То есть универсальный тип должен быть создан полностью. В приведенном выше примере пустые скобки (( и )) могут быть опущены, так как атрибут не имеет аргументов.

public class GenericType<T>
{
   [GenericAttribute<T>()] // Not allowed! generic attributes must be fully constructed types.
   public string Method() => default;
}

Аргументы типа должны соответствовать тем же ограничениям, что и оператор typeof. Типы, которым требуются аннотации метаданных, запрещены. Например, следующие типы не допускаются в качестве параметра типа:

  • dynamic
  • string? (или любой ссылочный тип, допускающий значение NULL)
  • (int X, int Y) (или любые другие типы кортежей, использующие синтаксис кортежей C#).

Эти типы не представлены непосредственно в метаданных. Они содержат заметки, описывающие тип. Во всех случаях можно использовать базовый тип:

  • object для dynamic.
  • string вместо string?.
  • ValueTuple<int, int> вместо (int X, int Y).

Поддержка универсальной математики

Существует несколько функций языка, которые обеспечивают поддержку универсальной математики:

  • static virtual элементы в интерфейсах
  • проверка определяемые пользователем операторы
  • расслабленные операторы смены
  • Оператор unsigned right-shift

Вы можете добавить или static virtual члены static abstract в интерфейсы, чтобы определить интерфейсы, включающие перегруженные операторы, другие статические члены и статические свойства. Основным сценарием для этой функции является использование математических операторов в универсальных типах. Например, интерфейс можно реализовать System.IAdditionOperators<TSelf, TOther, TResult> в типе, реализуемом operator +. Другие интерфейсы определяют другие математические операции или четко заданные значения. Вы можете узнать о новом синтаксисе в статье по интерфейсам. Интерфейсы, включающие static virtual методы, обычно являются универсальными интерфейсами. Кроме того, большинство объявляют ограничение, которое параметр типа реализует объявленный интерфейс.

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

Универсальная математика создала другие требования к языку.

  • Оператор без знака вправо: до C# 11 для принудительного принудительного отмены знака вправо необходимо привести любой целочисленный тип со знаком к типу без знака, выполнить смену, а затем вернуть результат к подписанному типу. Начиная с C# 11, можно использовать >>>оператор без знака shift.
  • Требования к оператору с расслабленным сдвигом: C# 11 удаляет требование, в которое второй операнд должен быть int или неявно intпреобразован в . Это изменение позволяет типам, реализующим универсальные математические интерфейсы, использовать в этих расположениях.
  • проверка и не проверка определяемые пользователем операторы: теперь разработчики могут определять checked и unchecked арифметические операторы. Компилятор создает вызовы правильного варианта на основе текущего контекста. Дополнительные сведения об checked операторах см. в статье об арифметических операторах.

Числовые IntPtr и UIntPtr

Теперь nint псевдоним System.IntPtrSystem.UIntPtrи nuint типы.

Новые строки в интерполяциях строк

Текст между символами { и } для интерполяции строки теперь может находиться на нескольких строках. Текст между метками { и } анализируется как код C#. Разрешен любой допустимый код C#, включая новые строки. Эта функция упрощает чтение интерполяций строк, использующих более длинные выражения C#, такие как выражения switch для сопоставления шаблонов или запросы LINQ.

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

Шаблоны списков

Шаблоны списков расширяют сопоставление шаблонов для сопоставления последовательностей элементов в списке или массиве. Например, sequence is [1, 2, 3] имеет значение true, если sequence является массивом или списком трех целых чисел (1, 2 и 3). Элементы можно сопоставлять с помощью любого шаблона, включая константу, тип, свойство и реляционные шаблоны. Шаблон отмены (_) сопоставляется с любым отдельным элементом, а новый шаблон диапазона (..) сопоставляется с любой последовательностью элементов (от нуля и больше).

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

Улучшенное преобразование групп методов для делегирования

Стандарт C# по преобразованиям групп методов теперь включает следующее:

  • Преобразованию разрешено (но не обязательно) использовать существующий экземпляр делегата, который уже содержит эти ссылки.

Предыдущие версии стандарта запрещали компилятору использовать повторно объект-делегат, созданный для преобразования группы методов. Компилятор C# 11 кэширует объект-делегат, созданный из преобразования группы методов и повторно использует такой отдельный объект-делегат. Эта функция была впервые доступна в Visual Studio 2022 версии 17.2 в качестве предварительной версии и в .NET 7 Preview 2.

Необработанные строковые литералы

Необработанные строковые литералы — это новый формат для строковых литералов. Необработанные строковые литералы могут содержать любой текст, в том числе пробелы, переходы строк, кавычки и другие специальные символы, без необходимости указывать escape-последовательности. Необработанный строковый литерал начинается с по меньшей мере трех символов двойных кавычек ("""). Заканчивается он таким же числом символов двойных кавычек. Как правило, необработанный строковый литерал использует три двойных кавычки на одной строке для указания начала строки и три двойных кавычки на отдельной строке для ее завершения. Новые линии после открывающей кавычки и предыдущие закрывающие кавычки не включаются в окончательное содержимое:

string longMessage = """
    This is a long message.
    It has several lines.
        Some are indented
                more than others.
    Some should start at the first column.
    Some have "quoted text" in them.
    """;

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

var location = $$"""
   You are at {{{Longitude}}, {{Latitude}}}
   """;

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

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

Автоматическая структура по умолчанию

Компилятор C# 11 гарантирует, что все поля struct типа инициализированы в значение по умолчанию в рамках выполнения конструктора. Это изменение означает, что любое поле или автоматическое свойство, не инициализированное конструктором, автоматически инициализируется компилятором. Структуры, в которых конструктор определенно не назначает все поля, которые теперь компилируются, и все поля, не инициализированные явным образом, задаются в качестве значения по умолчанию. Дополнительные сведения о том, как это изменение влияет на инициализацию структуры в статье по структурым.

Сопоставление Span<char> шаблонов или ReadOnlySpan<char> констант string

Вы смогли проверить string наличие определенного константного значения, используя сопоставление шаблонов для нескольких выпусков. Теперь можно использовать ту же логику сопоставления шаблонов с переменными, которые являются Span<char> или ReadOnlySpan<char>.

Расширенные имена область

Имена параметров типа и имена параметров теперь находятся в область при использовании в выражении в nameofобъявлении атрибутов для этого метода. Эта функция означает, что оператор может указывать nameof имя параметра метода в атрибуте в объявлении метода или параметра. Эта функция чаще всего полезна для добавления атрибутов для анализа, допускаемого значением NULL.

Строковые литералы UTF-8

Можно указать суффикс в строковом литерале, чтобы указать u8 кодировку символов UTF-8. Если приложению нужны строки UTF-8, для констант HTTP или аналогичных текстовых протоколов можно использовать эту функцию, чтобы упростить создание строк UTF-8.

Дополнительные сведения о строковых литералах UTF-8 см. в разделе строковых литеральных строк статьи по встроенным ссылочным типам.

Обязательные члены

Модификатор можно добавить required в свойства и поля для принудительного применения конструкторов и вызывающих объектов для инициализации этих значений. Его System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute можно добавить в конструкторы, чтобы сообщить компилятору, что конструктор инициализирует все необходимые элементы.

Дополнительные сведения о необходимых членах см. в разделе "Только для инициализации" статьи свойств.

ref поля и ref scoped переменные

Можно объявить ref поля внутри ref struct. Это поддерживает такие типы, как System.Span<T> без специальных атрибутов или скрытых внутренних типов.

Модификатор scoped можно добавить в любое ref объявление. Это ограничивает область, в которой ссылка может избежать.

Локальные типы файлов

Начиная с C# 11, можно использовать file модификатор доступа для создания типа, видимость которого область в исходный файл, в котором он объявлен. Эта функция помогает авторам исходного генератора избежать конфликтов именования. Дополнительные сведения об этой функции см. в статье о типах область файлов в справочнике по языку.

См. также