Бөлісу құралы:


Новые возможности 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 class или record struct. Классы и структуры, не являющиеся записями, могут не всегда хотеть такое поведение для параметров первичного конструктора.

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

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

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

Можно создать несколько типов, похожих на коллекции, без поддержки внешней библиотеки базовых классов (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];

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

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,

Элемент spread вычисляет каждый элемент выражения перечислений. Каждый элемент включается в выходную коллекцию.

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

параметры 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 см. в статье о модификаторах параметров в справочнике языка, или в спецификации функции «только для чтения» параметров .

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

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

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

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

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

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

Встроенные массивы используются командой среды выполнения и другими авторами библиотек для повышения производительности в ваших приложениях. Встроенные массивы позволяют разработчику создавать массив фиксированного размера в типе 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>

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

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

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

См. также