Partager via


Nouveautés de C# 12

C# 12 inclut les nouvelles fonctionnalités suivantes. Vous pouvez essayer ces fonctionnalités à l’aide de la dernière version visual Studio 2022 ou du 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 kit SDK .NET 8 le plus récent à partir de la page de téléchargements .NET. Vous pouvez également télécharger Visual Studio 2022, qui inclut le Kit de développement logiciel (SDK) .NET 8.

Remarque

Nous sommes intéressés par vos commentaires sur ces fonctionnalités. 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 vous assurer que tous les paramètres du constructeur principal sont assurément attribués, tous les constructeurs explicitement déclarés doivent appeler le constructeur principal à l'aide de la syntaxe this(). L’ajout d’un constructeur principal à un 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, record class ou record struct types. Les classes et structs non enregistrés peuvent ne pas toujours vouloir ce comportement pour les paramètres du constructeur principal.

Vous pouvez en savoir plus sur les constructeurs principaux dans le didacticiel pour explorer les constructeurs principaux et dans l’article sur les constructeurs d’instance .

Expressions de collection

Les expressions de collection introduisent une nouvelle syntaxe terse pour créer des valeurs de collection courantes. L’incorporation d’autres collections dans ces valeurs est possible à l’aide d’un élément de propagation ..e.

Plusieurs types semblables à des collections peuvent être créés sans nécessiter de support BCL externe. Ces types sont les suivants :

Les exemples suivants montrent les 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'élément spread, ..e dans une expression de collection ajoute tous les éléments de cette expression. L'argument doit être un type de collection. Les exemples suivants montrent comment fonctionne l’élément 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’élément de propagation évalue chaque élément de l’expression d’énumérations. Chaque élément est inclus dans la collection de résultats.

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 de ref readonly

C# a ajouté les paramètres in comme moyen de passer des références en lecture seule. Les paramètres in permettent l'utilisation de variables et de valeurs, et peuvent être utilisés sans aucune 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 des paramètres in :

  • Les API créées avant l’introduction de in peuvent utiliser ref même si l’argument n’est pas modifié. Ces API peuvent être mises à jour avec ref readonly. Il ne s'agit pas d'un changement radical pour les appelants, comme ce serait le cas si le paramètre ref était remplacé par in. Par exemple, System.Runtime.InteropServices.Marshal.QueryInterface.
  • Les API qui prennent un paramètre in, mais nécessitent logiquement une variable. Une expression de valeur ne fonctionne pas. Par exemple, System.ReadOnlySpan<T>.ReadOnlySpan<T>(T).
  • Les API qui utilisent ref, car elles nécessitent une variable, mais ne mutent pas cette variable. Par exemple, System.Runtime.CompilerServices.Unsafe.IsNullRef.

Pour en savoir plus sur les paramètres ref readonly, consultez l'article sur les modificateurs de paramètres dans la référence du langage, ou la spécification de la fonctionnalité ref readonly parameters.

Paramètres lambda par défaut

Vous pouvez maintenant définir des valeurs par défaut pour les paramètres sur les expressions lambda. La syntaxe et les règles sont identiques à l’ajout de valeurs par défaut pour les arguments à n’importe quelle méthode ou fonction locale.

Vous pouvez en savoir plus sur les paramètres par défaut sur les expressions lambda dans l’article sur expressions lambda.

Alias de n'importe quel type

Vous pouvez utiliser la directive d’alias using pour alias 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 de tableaux, les types de pointeur ou d’autres types non sécurisés. Pour plus d’informations, consultez la spécification de fonctionnalité . Pour obtenir un exemple de procédure pas à pas de refactorisation, consultez Refactoriser votre code à l’aide d’alias n’importe quel type sur le blog .NET.

Tableaux inline

Les tableaux inline sont utilisés par l’équipe runtime et d’autres auteurs de bibliothèque pour améliorer les performances de vos applications. Les tableaux inline permettent au 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 à 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 runtime.

Un tableau inline est déclaré similaire à la structsuivante :

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

Vous les utilisez 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 tirer parti des informations connues sur un tableau inline. Vous pouvez utiliser les tableaux en ligne comme n'importe quel autre tableau. Pour plus d'informations sur la manière de déclarer des tableaux en ligne, consultez la référence du langage sur les types struct.

Attribut expérimental

Les types, méthodes ou assemblys peuvent être marqués avec le 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és avec le ExperimentalAttribute. Tous les types inclus dans un assembly marqué avec l’attribut Experimental sont expérimentaux. Vous pouvez en savoir plus dans l’article sur les attributs généraux lus par le compilateur, ou la spécification de fonctionnalité .

Intercepteurs

Avertissement

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

Pour 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 à une méthode interceptable par un appel à lui-même au moment de la compilation. Cette substitution se produit lorsque l’intercepteur déclare les emplacements sources des appels qu’il intercepte. Les intercepteurs offrent une capacité limitée à modifier la sémantique du code existant en ajoutant du nouveau code à une compilation, par exemple dans un générateur de code source.

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

Si vous souhaitez expérimenter des intercepteurs, vous pouvez en savoir plus en lisant la spécification de fonctionnalité . Si vous utilisez la fonctionnalité, veillez à rester informé des modifications apportées à la spécification de fonctionnalité pour cette fonctionnalité expérimentale. Si la fonctionnalité est finalisée, nous ajouterons des conseils supplémentaires sur ce site.

Voir aussi