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

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

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

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

Примечание.

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

Основные конструкторы

Теперь вы можете создавать первичные конструкторы в любом class и struct. Основные конструкторы больше не ограничиваются типами record . Основные параметры конструктора находятся в область для всего текста класса. Чтобы убедиться, что все параметры первичного конструктора определенно назначены, все явно объявленные конструкторы должны вызывать основной конструктор с помощью this() синтаксиса. Добавление первичного конструктора в class объект запрещает компилятору объявлять неявный конструктор без параметров. structВ неявном конструкторе без параметров инициализирует все поля, включая параметры первичного конструктора в 0-битовый шаблон.

Компилятор создает общедоступные свойства для параметров первичного конструктора только в record типах или record classrecord struct типах. Некорректные классы и структуры могут не всегда использовать это поведение для параметров первичного конструктора.

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

Выражения коллекции

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

Можно создать несколько типов, таких как коллекция, без поддержки внешнего BCL. Это следующие типы:

В следующих примерах показано использование выражений коллекции:

// Create an array:
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];

// Create a list:
List<string> b = ["one", "two", "three"];

// Create a span
Span<char> c  = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];

// Create a jagged 2D array:
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

// Create a jagged 2D array from variables:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[][] twoDFromVariables = [row0, row1, row2];

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

int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[] single = [.. row0, .. row1, .. row2];
foreach (var element in single)
{
    Console.Write($"{element}, ");
}
// output:
// 1, 2, 3, 4, 5, 6, 7, 8, 9,

Операнды оператора распространения — это выражение, которое можно перечислить. Оператор распространения вычисляет каждый элемент выражения перечислений.

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

параметры ref readonly

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

ref readonly Добавление параметров обеспечивает более четкость для API, которые могут использовать ref параметры или in параметры:

  • Интерфейсы API, созданные ранее, in могут использовать ref , даже если аргумент не изменен. Эти API можно обновить с помощью ref readonly. Это не будет критическим изменением для вызывающих абонентов, как было бы, если ref параметр был изменен inна . Например, System.Runtime.InteropServices.Marshal.QueryInterface.
  • API, которые принимают in параметр, но логически требуют переменной. Выражение значения не работает. Например, System.ReadOnlySpan<T>.ReadOnlySpan<T>(T).
  • API, которые используются ref , так как им требуется переменная, но не мутируют эти переменные. Например, System.Runtime.CompilerServices.Unsafe.IsNullRef.

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

Параметры лямбда-кода по умолчанию

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

Дополнительные сведения о параметрах по умолчанию для лямбда-выражений см. в статье об лямбда-выражениях.

Псевдоним любого типа

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

Встроенные массивы

Встроенные массивы используются командой среды выполнения и другими авторами библиотек для повышения производительности в приложениях. Встроенные массивы позволяют разработчику создавать массив фиксированного размера в типе struct . Структуру с встроенным буфером следует обеспечить характеристики производительности, аналогичные небезопасной буферу фиксированного размера. Скорее всего, вы не объявите собственные встроенные массивы, но вы используете их прозрачно, когда они предоставляются как System.Span<T> или System.ReadOnlySpan<T> объекты из API среды выполнения.

Встроенный массив объявлен следующим образом struct:

[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
    private int _element0;
}

Они используются как любой другой массив:

var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
    buffer[i] = i;
}

foreach (var i in buffer)
{
    Console.WriteLine(i);
}

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

Экспериментальный атрибут

Типы, методы или сборки можно помечать с System.Diagnostics.CodeAnalysis.ExperimentalAttribute помощью элемента, указывающего экспериментальную функцию. Компилятор выдает предупреждение при доступе к методу или типу, аннотированному ExperimentalAttributeс помощью . Все типы, включенные в сборку, помеченную атрибутом Experimental , являются экспериментальными. Дополнительные сведения см. в статье об общих атрибутах компилятора или спецификации компонентов.

Перехватчики

Предупреждение

Перехватчики — это экспериментальная функция, доступная в режиме предварительной версии с C# 12. Эта функция может быть подвержена критическим изменениям или удалению в будущем выпуске. Поэтому не рекомендуется для рабочих или выпущенных приложений.

Чтобы использовать перехватчики, проект пользователя должен указать свойство <InterceptorsPreviewNamespaces>. Это список пространств имен, которые могут содержать перехватчики.

Например: <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPreviewNamespaces>

Перехватчик — это метод, который может декларативно заменить вызов перехватываемого метода вызовом к себе во время компиляции. Эта подстановка происходит путем объявления перехватчиком исходных расположений вызовов, которые он перехватывает. Перехватчики предоставляют ограниченное средство для изменения семантики существующего кода путем добавления нового кода в компиляцию, например в генератор источника.

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

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

См. также