Nouveautés de C# 12

C# 12 intègre les nouvelles fonctionnalités suivantes. Vous pouvez essayer ces fonctionnalités à l’aide de la dernière version de Visual Studio 2022 ou du Kit de développement logiciel (SDK) .NET 8.

C# 12 est pris en charge sur .NET 8. Pour plus d’informations, consultez Contrôle de version du langage C#.

Vous pouvez télécharger le dernier SDK .NET 8 à partir de la page de téléchargements .NET. Vous pouvez également télécharger Visual Studio 2022 qui comprend le SDK .NET 8.

Remarque

Vos commentaires sur ces fonctionnalités nous intéressent. Si vous rencontrez des problèmes avec l’une de ces nouvelles fonctionnalités, créez un nouveau problème dans le référentiel dotnet/roslyn.

Constructeurs principaux

Vous pouvez désormais créer des constructeurs principaux dans n’importe quel class et struct. Les constructeurs principaux ne sont plus limités aux types record. Les paramètres de constructeur principal se trouvent dans l’étendue de l’ensemble du corps de la classe. Pour garantir l’affectation définitive de tous les paramètres de constructeur principal, tous les constructeurs explicitement déclarés doivent appeler le constructeur principal à l’aide de la syntaxe this(). L’ajout d’un constructeur principal à class empêche le compilateur de déclarer un constructeur sans paramètre implicite. Dans struct, le constructeur sans paramètre implicite initialise tous les champs, notamment les paramètres de constructeur principal selon le modèle 0 bit.

Le compilateur génère des propriétés publiques pour les paramètres de constructeur principal uniquement dans les types record, qu’il s’agisse des types record class ou record struct. Les classes et les structs qui ne sont pas des enregistrements ne souhaitent pas toujours ce comportement pour les paramètres de constructeur principal.

Pour plus d’informations sur les constructeurs principaux, consultez le tutoriel sur l’exploration des constructeurs principaux et l’article sur constructeurs d’instances.

Expressions de collection

Les expressions de collection introduisent une nouvelle syntaxe concise pour créer des valeurs de collection courantes. L’inlining d’autres collections dans ces valeurs est possible à l’aide d’un opérateur de propagation ...

Plusieurs types de collection peuvent être créés sans nécessiter de prise en charge BCL externe. Ces types sont les suivants :

Les exemples suivants présentent des utilisations d’expressions de collection :

// 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];

L’opérateur de propagation, .. dans une expression de collection remplace son argument par les éléments de cette collection. L’argument doit être un type de collection. Les exemples suivants montrent comment fonctionne l’opérateur de propagation :

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,

L’opérande d’un opérateur de propagation est une expression qui peut être énumérée. L’opérateur de propagation évalue chaque élément de l’expression des énumérations.

Vous pouvez utiliser des expressions de collection partout où vous avez besoin d’une collection d’éléments. Ils peuvent spécifier la valeur initiale d’une collection ou être passés en tant qu’arguments aux méthodes qui acceptent des types de collection. Vous pouvez en savoir plus sur les expressions de collection dans l’article de référence du langage sur les expressions de collection ou la spécification de fonctionnalité.

Paramètres ref readonly

C# a ajouté des paramètres in comme moyen de passer des références en lecture seule. Les paramètres in autorisent à la fois les variables et les valeurs, et peuvent être utilisés sans annotation sur les arguments.

L’ajout de paramètres ref readonly permet une plus grande clarté pour les API qui peuvent utiliser des paramètres ref ou in :

Pour en savoir plus sur les paramètres ref readonly, consultez l’article sur les modificateurs de paramètres dans la référence de langage ou la spécification des caractéristiques des paramètres ref en lecture seule.

Paramètres lambda par défaut

Vous pouvez désormais définir des valeurs par défaut pour les paramètres dans les expressions lambda. La syntaxe et les règles sont les mêmes que celles qui permettent d’ajouter les valeurs par défaut des arguments à une méthode ou une fonction locale.

Pour en savoir plus sur les paramètres par défaut des expressions lambda, consultez l’article relatif aux expressions lambda.

Alias de n’importe quel type

Vous pouvez utiliser la directive d’alias using pour créer un alias de n’importe quel type, pas seulement les types nommés. Cela signifie que vous pouvez créer des alias sémantiques pour les types tuple, les types tableau, les types pointeur ou d’autres types unsafe. Pour plus d’informations, consultez la spécification de fonctionnalité.

Tableaux inline

Les tableaux inline sont utilisés par l’équipe de runtime et d’autres auteurs de bibliothèques pour améliorer les performances de vos applications. Les tableaux inline permettent à un développeur de créer un tableau de taille fixe dans un type struct. Un struct avec une mémoire tampon inline doit fournir des caractéristiques de performances similaires à celles fournies par une mémoire tampon de taille fixe non sécurisée. Vous ne déclarez probablement pas vos propres tableaux inline, mais vous les utilisez de manière transparente lorsqu’ils sont exposés en tant qu’objets System.Span<T> ou System.ReadOnlySpan<T> à partir d’API d’exécution.

Un tableau inline est déclaré similaire à ce qui suit struct:

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

Vous les utiliserez comme n’importe quel autre tableau :

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

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

La différence est que le compilateur peut exploiter les informations connues sur un tableau inline. Vous consommez probablement les tableaux inline comme vous le feriez pour tout autre tableau. Pour plus d’informations sur la manière de déclarer des tableaux inline, consultez la référence de langage sur struct les types.

Attribut expérimental

Les types, méthodes ou assemblys peuvent être marqués de System.Diagnostics.CodeAnalysis.ExperimentalAttribute pour indiquer une fonctionnalité expérimentale. Le compilateur émet un avertissement si vous accédez à une méthode ou un type annoté de ExperimentalAttribute. Tous les types déclarés dans un assembly ou un module marqués avec l’attribut Experimental sont expérimentaux. Pour en savoir plus, consultez l’article sur les attributs généraux lus par le compilateur ou la spécification des fonctionnalités.

Intercepteurs

Warning

Les intercepteurs sont une fonctionnalité expérimentale, disponible en préversion avec C# 12. La fonctionnalité peut faire l’objet de changements cassants ou de suppressions dans une version ultérieure. Par conséquent, elles ne sont pas recommandées pour des applications en production ou publiées.

Afin d’utiliser des intercepteurs, le projet utilisateur doit spécifier la propriété <InterceptorsPreviewNamespaces>. Il s’agit d’une liste d’espaces de noms autorisés à contenir des intercepteurs.

Par exemple : <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPreviewNamespaces>

Un intercepteur est une méthode qui peut remplacer de manière déclarative un appel vers une méthode interceptable par un appel vers lui-même au moment de la compilation. Cette substitution se produit en demandant à l’intercepteur de déclarer les emplacements sources des appels qu’il intercepte. Les intercepteurs offrent une possibilité limitée de modifier la sémantique du code existant en ajoutant du nouveau code à une compilation, par exemple dans un générateur de source.

Vous utilisez un intercepteur dans le cadre d’un générateur de source pour modifier, plutôt qu’ajouter du code à une compilation source existante. Le générateur de source remplace les appels vers une méthode interceptable par un appel vers la méthode d’intercepteur.

Si vous souhaitez expérimenter les intercepteurs, vous pouvez en savoir plus en lisant la spécification de fonctionnalité. Si vous utilisez la fonctionnalité, veillez à rester à jour sur les modifications apportées à la spécification de cette fonctionnalité expérimentale. Si la fonctionnalité est finalisée, nous ajouterons d’autres conseils sur ce site.

Voir aussi