Partager via


Nouveautés de la version 11 de C#

Les fonctionnalités suivantes ont été ajoutées dans C# 11 :

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

Vous pouvez télécharger la dernière version du kit de développement logiciel (SDK) .NET 7 depuis la page de téléchargements .NET. Vous pouvez également télécharger Visual Studio 2022 qui comprend la version 7 du kit de développement logiciel (SDK) .NET.

Notes

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.

Attributs génériques

Vous pouvez déclarer une classe générique dont la classe de base est System.Attribute. Cette fonctionnalité fournit une syntaxe plus pratique pour les attributs qui exigent un paramètre System.Type. Auparavant, il était nécessaire de créer un attribut qui prenait un Type comme paramètre de constructeur :

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

   public Type ParamType { get; }
}

Pour appliquer l’attribut, il fallait utiliser l’opérateur typeof :

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

À l’aide de cette nouvelle fonctionnalité, vous pouvez créer plutôt un attribut générique :

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

Ensuite, vous spécifiez le paramètre de type permettant d’utiliser l’attribut :

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

Vous devez fournir tous les paramètres de type lorsque vous appliquez l’attribut. En d’autres termes, le type générique doit être entièrement construit. Dans l’exemple ci-dessus, les parenthèses vides (( et )) peuvent être omises car l’attribut n’a pas d’arguments.

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

Les arguments de type doivent respecter les mêmes restrictions que l’opérateur typeof . Les types qui exigent des annotations de métadonnées ne sont pas autorisés comme paramètres de type, par exemple :

  • dynamic
  • string? (ou tout type référence Nullable)
  • (int X, int Y) (ou tout autre type de tuple suivant la syntaxe de tuple C#)

Ces types ne sont pas directement représentés dans les métadonnées. Ils incluent des annotations qui les décrivent. Dans tous les cas, vous pouvez utiliser le type sous-jacent à la place :

  • object plutôt que dynamic
  • string plutôt que string?.
  • ValueTuple<int, int> plutôt que (int X, int Y).

Prise en charge des mathématiques génériques

Plusieurs fonctionnalités de langage prennent en charge les mathématiques génériques :

  • Membres static virtual dans les interfaces
  • Opérateurs checked définis par l’utilisateur
  • Opérateurs de décalage souples
  • Opérateur de décalage vers la droite non signé

Vous pouvez ajouter des membres static abstract ou static virtual dans des interfaces pour définir des interfaces qui incluent des opérateurs surchargeables, d’autres membres statiques et des propriétés statiques. Le scénario principal de cette fonctionnalité consiste à utiliser des opérateurs mathématiques dans des types génériques. Par exemple, vous pouvez implémenter l’interface System.IAdditionOperators<TSelf, TOther, TResult> dans un type qui implémente operator +. D’autres interfaces définissent d’autres opérations mathématiques ou valeurs bien définies. Pour en savoir plus sur la nouvelle syntaxe, consultez l’article sur les interfaces. Les interfaces qui incluent des méthodes static virtual sont généralement des interfaces génériques. De plus, la plupart déclarent une contrainte selon laquelle le paramètre de type implémente l’interface déclarée.

Pour plus d’informations ou pour essayer la fonctionnalité vous-même, consultez le tutoriel Exploration des membres abstraits statiques de l’interface ou le billet de blog Fonctionnalités d’évaluation de .NET 6 – Mathématiques génériques.

Les mathématiques génériques imposent d’autres exigences au langage.

  • Opérateur de décalage vers la droite non signé : avant C# 11, pour forcer un décalage vers la droite non signé, vous deviez caster tout type entier signé en type non signé, effectuer le décalage, puis recaster le résultat en type signé. À partir de C# 11, vous pouvez utiliser l’opérateur de décalage non signé>>>.
  • Exigences de l’opérateur de décalage souple : C# 11 élimine l’exigence selon laquelle le deuxième opérande doit être un int ou être implicitement convertible en int. Cette modification permet d’utiliser des types qui implémentent des interfaces mathématiques génériques dans ces emplacements.
  • Opérateurs checked et unchecked définis par l’utilisateur : les développeurs peuvent désormais définir les opérateurs arithmétiques checked et unchecked. Le compilateur génère des appels à la variante appropriée en fonction du contexte actuel. Pour en savoir plus sur les opérateurs checked, consultez l’article sur les opérateurs arithmétiques.

Types numériques IntPtr et UIntPtr

Les types nint et nuint sont désormais les alias de System.IntPtr et de System.UIntPtr, respectivement.

Nouvelles lignes dans les interpolations de chaînes

Le texte situé à l’intérieur des caractères { et } d’une interpolation de chaîne peut désormais s’étendre sur plusieurs lignes. Le texte qui se trouve entre les marqueurs { et } est analysé comme du code C#. Tout le code C# valide, y compris les nouvelles lignes, est autorisé. Cette fonctionnalité facilite la lecture des interpolations de chaînes qui utilisent de longues expressions C#, comme les expressions switch de critères spéciaux et les requêtes LINQ.

Pour plus d’informations sur la fonctionnalité de nouvelles lignes, consultez l’article Interpolations de chaînes dans la documentation de référence du langage.

Modèles de liste

Les modèles de liste étendent les critères spéciaux pour intégrer la correspondance avec des séquences d’éléments d’une liste ou d’un tableau. Par exemple, sequence is [1, 2, 3] est true lorsque sequence est un tableau ou une liste de trois entiers (1, 2 et 3). Vous pouvez faire correspondre des éléments à l’aide de n’importe quel modèle, notamment des modèles constants et relationnels et des modèles de type et de propriété. Le modèle discard (_) correspond à n’importe quel élément unique, et le nouveau modèle de plage (..) à n’importe quelle séquence de zéro, un ou plusieurs éléments.

Pour plus d’informations sur les modèles de liste, consultez l’article Critères spéciaux dans la documentation de référence du langage.

Amélioration de la conversion de groupe de méthodes en instance déléguée

Le standard C# des Conversions de groupes de méthodes inclut désormais l’élément suivant :

  • La conversion est autorisée (mais non obligatoire) pour utiliser une instance déléguée existante qui contient déjà ces références.

Les versions précédentes du standard empêchaient le compilateur de réutiliser l’objet délégué créé pour une conversion de groupe de méthodes. Le compilateur de la version 11 de C# le met en cache et le réutilise. Cette fonctionnalité a été introduite dans Visual Studio 2022 version 17.2 en préversion et dans .NET 7 Preview 2.

Littéraux de chaîne bruts

Les littéraux de chaîne brute constituent un nouveau format pour les littéraux de chaîne. Ils peuvent contenir du texte arbitraire, y compris des espaces blancs, de nouvelles lignes, des guillemets incorporés et d’autres caractères spéciaux, sans nécessiter de séquences d’échappement. Un littéral de chaîne brute commence par au moins trois caractères guillemets doubles ("""). Il se termine par le même nombre de guillemets doubles. En règle générale, il utilise trois guillemets doubles sur une seule ligne pour démarrer la chaîne, et trois guillemets doubles sur une ligne distincte pour la terminer. Les nouvelles lignes qui suivent le guillemet ouvrant et qui précèdent le guillemet fermant ne sont pas inclus dans le contenu final :

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.
    """;

Tout espace blanc situé à gauche des guillemets doubles fermants est supprimé du littéral de chaîne. Les littéraux de chaîne brute peuvent être combinés avec l’interpolation de chaîne pour inclure des accolades dans le texte de sortie. Plusieurs caractères $ indiquent le nombre d’accolades consécutives qui commencent et terminent l’interpolation :

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

L’exemple précédent spécifie que deux accolades commencent et terminent une interpolation. La troisième accolade ouvrante et fermante est incluse dans la chaîne de sortie.

Pour plus d’informations sur les littéraux de chaîne brute, consultez l’article Chaînes dans le guide de programmation, ainsi que les articles Littéraux de chaîne et Chaînes interpolées dans la documentation de référence du langage.

Struct par défaut automatique

Le compilateur C# 11 garantit que tous les champs d’un type struct sont initialisés à leur valeur par défaut dans le cadre de l’exécution d’un constructeur. Cette modification signifie que tout champ ou propriété automatique non initialisé par un constructeur est automatiquement initialisé par le compilateur. Les structs dans lesquels le constructeur n’affecte pas définitivement tous les champs sont maintenant compilés, et tous les champs qui ne sont pas initialisés explicitement sont définis avec leur valeur par défaut. Pour en savoir plus sur la façon dont cette modification affecte l’initialisation des structs, consultez l’article sur les structs.

Critères spéciaux avec Span<char> ou ReadOnlySpan<char> sur une constante string

Depuis plusieurs versions, vous pouvez utiliser les critères spéciaux pour tester si un string a une valeur constante spécifique. Vous pouvez désormais utiliser la même logique des critères spéciaux avec des variables Span<char> ou ReadOnlySpan<char>.

Portée nameof étendue

Les noms de paramètre de type et les noms de paramètre sont désormais dans la portée quand ils sont utilisés dans une expression nameof dans une déclaration d’attribut sur cette méthode. Cette fonctionnalité signifie que vous pouvez utiliser l’opérateur nameof pour spécifier le nom d’un paramètre de méthode dans un attribut sur la déclaration de méthode ou de paramètre. Cette fonctionnalité est le plus souvent utile pour ajouter des attributs à l’analyse de l’état null.

Littéraux de chaîne UTF-8

Vous pouvez spécifier le suffixe u8 sur un littéral de chaîne pour spécifier le codage de caractères UTF-8. Si votre application a besoin de chaînes UTF-8, pour des constantes de chaîne HTTP ou des protocoles de texte similaires, vous pouvez utiliser cette fonctionnalité pour simplifier la création de chaînes UTF-8.

Pour en savoir plus sur les littéraux de chaîne UTF-8, consultez la section sur les littéraux de chaîne de l’article sur les types de référence intégrés.

Membres nécessaires

Vous pouvez ajouter le requiredmodificateur à des propriétés et à des champs pour obliger les constructeurs et les appelants à initialiser ces valeurs. Vous pouvez ajouter System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute à des constructeurs pour informer le compilateur qu’un constructeur initialise tous les membres obligatoires.

Pour plus d’informations sur les membres obligatoires, consultez la section init-only de l’article sur les propriétés.

Champs ref et variables ref scoped

Vous pouvez déclarer des champs ref dans un ref struct. Cela permet de prendre en charge des types tels que System.Span<T> sans attributs spéciaux ou types internes masqués.

Vous pouvez ajouter le modificateur scoped à n’importe quelle déclaration ref. Cela limite la portée où la référence peut être échappée.

Types locaux de fichiers

À partir de C# 11, vous pouvez utiliser le modificateur d’accès file pour créer un type dont la visibilité est limitée au fichier source dans lequel il est déclaré. Cette fonctionnalité permet aux auteurs de générateurs de source d’éviter les collisions de noms. Pour en savoir plus sur cette fonctionnalité, consultez l’article sur les types inclus dans la portée du fichier dans la référence du langage.

Voir aussi