Nouveautés de C# 13
C# 13 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 9:
- Collections
params
- Nouveau type de
lock
et sémantique. - Nouvelle séquence d’échappement -
\e
. - Améliorations du type naturel du groupe de méthodes
- Accès à l’indexeur implicite dans les initialiseurs d’objets
- Activer les variables locales
ref
et les contextesunsafe
dans les itérateurs et les méthodes asynchrones - Activer les types
ref struct
pour implémenter des interfaces. - Autoriser les types ref struct comme arguments pour les paramètres de type génériques.
- Les propriétés partielles et les indexeurs sont désormais autorisés dans les types
partial
. - La priorité de résolution de surcharge permet aux auteurs de bibliothèque de désigner une surcharge comme étant meilleure que les autres.
À compter de Visual Studio 17.12, C# 13 inclut le mot clé contextuel field
comme fonctionnalité d’aperçu.
C# 13 est pris en charge par .NET 9. Pour plus d’informations, consultez Contrôle de version du langage C#.
Vous pouvez télécharger la dernière version du kit SDK .NET 9 à partir de la page téléchargements .NET . Vous pouvez également télécharger Visual Studio 2022, qui inclut le Kit de développement logiciel (SDK) .NET 9.
De nouvelles fonctionnalités sont ajoutées à la page « Nouveautés en C# » lorsqu’elles sont disponibles dans les versions en préversion publique. La section ensemble de travail de la page d’état des fonctionnalités de Roslyn suit le moment où les nouvelles fonctionnalités sont fusionnées dans la branche principale.
Vous pouvez trouver tous les changements cassants introduits dans C# 13 dans notre article sur les changements cassants.
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.
Collections params
Le modificateur params
n’est pas limité aux types de tableaux. Vous pouvez maintenant utiliser params
avec n’importe quel type de collection reconnu, y compris System.Span<T>, System.ReadOnlySpan<T>et les types qui implémentent System.Collections.Generic.IEnumerable<T> et ont une méthode de Add
. En plus des types concrets, les interfaces System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.IReadOnlyList<T>, System.Collections.Generic.ICollection<T>et System.Collections.Generic.IList<T> peuvent également être utilisées.
Lorsqu’un type d’interface est utilisé, le compilateur synthétise le stockage des arguments fournis. Vous pouvez en savoir plus dans la spécification des fonctionnalités pour les collections params
.
Par exemple, les déclarations de méthode peuvent déclarer des étendues en tant que paramètres params
:
public void Concat<T>(params ReadOnlySpan<T> items)
{
for (int i = 0; i < items.Length; i++)
{
Console.Write(items[i]);
Console.Write(" ");
}
Console.WriteLine();
}
Nouvel objet de verrouillage
Le runtime .NET 9 inclut un nouveau type pour la synchronisation de threads, le type System.Threading.Lock. Ce type fournit une meilleure synchronisation de threads via son API. La méthode Lock.EnterScope() entre dans un cadre exclusif. Le ref struct
renvoyé par ce dernier prend en charge le modèle Dispose()
pour quitter la portée exclusive.
L’instruction lock
C# reconnaît si la cible du verrou est un objet Lock
. Dans ce cas, il utilise l’API mise à jour, plutôt que l’API traditionnelle à l’aide de System.Threading.Monitor. Le compilateur reconnaît également si vous convertissez un objet Lock
en un autre type et que le code basé sur Monitor
sera généré. Vous pouvez en savoir plus dans la spécification des fonctionnalités pour le nouvel objet de verrouillage .
Cette fonctionnalité vous permet de bénéficier du nouveau type de bibliothèque en modifiant le type d’objet que vous utilisez avec lock
. Aucun autre code n’a besoin de changer.
Nouvelle séquence d’échappement
Vous pouvez utiliser \e
comme une séquence d’échappement de littéral de caractère pour le caractère ESCAPE
, Unicode U+001B
. Auparavant, vous avez utilisé \u001b
ou \x1b
. L’utilisation de \x1b
n’a pas été recommandée, car si les caractères suivants 1b
étaient des chiffres hexadécimaux valides, ces caractères font partie de la séquence d’échappement.
Type naturel de groupe de méthodes
Cette fonctionnalité permet de petites optimisations pour la résolution de la surcharge qui impliquent des groupes de méthodes. Un groupe de méthodes est une méthode et toutes les surcharges ont le même nom. Le comportement précédent était destiné au compilateur à construire l’ensemble complet de méthodes candidates pour un groupe de méthodes. Si un type naturel était nécessaire, le type naturel a été déterminé à partir de l’ensemble complet de méthodes candidates.
Le nouveau comportement consiste à découper l’ensemble des méthodes candidates à chaque étendue, en supprimant les méthodes candidates qui ne sont pas applicables. En règle générale, les méthodes supprimées sont des méthodes génériques avec une arité incorrecte ou des contraintes qui ne sont pas satisfaites. Le processus continue jusqu’à la portée externe suivante uniquement si aucune méthode candidate n’est trouvée. Ce processus suit de plus près l’algorithme général pour la résolution de surcharge. Si toutes les méthodes candidates trouvées dans une étendue donnée ne correspondent pas, le groupe de méthodes n’a pas de type naturel.
Vous pouvez lire les détails des modifications dans la spécification de la proposition .
Accès implicite à l’index
L’opérateur d’index implicite « à partir de la fin », ^
, est désormais autorisé dans une expression d’initialiseur d’objet. Par exemple, vous pouvez maintenant initialiser un tableau dans un initialiseur d’objet, comme indiqué dans le code suivant :
public class TimerRemaining
{
public int[] buffer { get; set; } = new int[10];
}
var countdown = new TimerRemaining()
{
buffer =
{
[^1] = 0,
[^2] = 1,
[^3] = 2,
[^4] = 3,
[^5] = 4,
[^6] = 5,
[^7] = 6,
[^8] = 7,
[^9] = 8,
[^10] = 9
}
};
La classe TimerRemaining
inclut un tableau buffer
initialisé à une longueur de 10. L’exemple précédent assigne des valeurs à ce tableau à l’aide de l’opérateur d’index « de la fin » (^
), créant ainsi un tableau qui décompte de 9 à 0.
Dans les versions antérieures à C# 13, l’opérateur ^
ne peut pas être utilisé dans un initialiseur d’objet. Vous devez indexer les éléments à partir du début.
ref
et unsafe
dans les itérateurs et les méthodes async
Cette fonction et les deux suivantes permettent aux types ref struct
d'utiliser de nouvelles structures. Vous ne les utiliserez pas, sauf si vous écrivez vos propres types ref struct
. Plus probablement, vous verrez un avantage indirect à mesure que System.Span<T> et System.ReadOnlySpan<T> gagnent plus de fonctionnalités.
Avant C# 13, les méthodes d’itérateur (méthodes qui utilisent yield return
) et les méthodes async
n’ont pas pu déclarer des variables ref
locales ni avoir un contexte unsafe
.
En C# 13, async
méthodes peuvent déclarer des variables locales ref
ou des variables locales d’un type ref struct
. Toutefois, ces variables ne sont pas accessibles à travers une limite de await
. Elle ne peuvent pas non plus être accessibles à travers une limite yield return
.
Cette restriction assouplie permet au compilateur d’autoriser l’utilisation vérifiable de ref
variables locales et de types ref struct
dans d’autres endroits. Vous pouvez utiliser en toute sécurité des types comme System.ReadOnlySpan<T> dans ces méthodes. Le compilateur vous indique si vous ne respectez pas les règles de sécurité.
De la même façon, C# 13 permet les contextes unsafe
dans les fonctions itératrices. Toutefois, toutes les instructions yield return
et yield break
doivent se trouver dans des contextes sécurisés.
allows ref struct
Avant C# 13, ref struct
types n’ont pas pu être déclarés comme argument de type pour un type ou une méthode générique. À présent, les déclarations de type générique peuvent ajouter une anti-contrainte, allows ref struct
. Cette anti-contrainte déclare que l’argument de type fourni pour ce paramètre de type peut être un type ref struct
. Le compilateur applique des règles de sécurité ref à toutes les instances de ce paramètre de type.
Par exemple, vous pouvez déclarer un type générique comme le code suivant :
public class C<T> where T : allows ref struct
{
// Use T as a ref struct:
public void M(scoped T p)
{
// The parameter p must follow ref safety rules
}
}
Cela permet aux types tels que System.Span<T> et System.ReadOnlySpan<T> d’être utilisés avec des algorithmes génériques, le cas échéant. Vous pouvez en savoir plus dans les mises à jour de where
et l’article du guide de programmation sur les contraintes génériques .
Interfaces ref struct
Avant C# 13, ref struct
types n’ont pas été autorisés à implémenter des interfaces. Elles sont accessibles à partir de C# 13. Vous pouvez déclarer qu’un type ref struct
implémente une interface. Toutefois, pour garantir les règles de sécurité de référence, un type ref struct
ne peut pas être converti en type d’interface. Il s’agit d’une conversion boxing qui pourrait violer la sécurité des références. Les déclarations de méthode d’interface explicites dans une ref struct
sont accessibles uniquement via un paramètre de type où ce paramètre de type allows ref struct
. En outre, ref struct
types doivent implémenter toutes les méthodes déclarées dans une interface, y compris ces méthodes avec une implémentation par défaut.
En savoir plus sur les mises à jour sur les types ref struct
et l’ajout de la contrainte générique allows ref struct
.
Plus de membres partiels
Vous pouvez déclarer des propriétés partial
et des indexeurs partial
dans C# 13. Les propriétés partielles et les indexeurs suivent généralement les mêmes règles que les méthodes partial
: vous créez une déclaration de déclaration et une déclaration d’implémentation. Les signatures des deux déclarations doivent correspondre. Une restriction est que vous ne pouvez pas utiliser une déclaration de propriété automatique pour implémenter une propriété partielle. Les propriétés qui ne déclarent pas de corps sont considérées comme la déclaration de déclaration.
public partial class C
{
// Declaring declaration
public partial string Name { get; set; }
}
public partial class C
{
// implementation declaration:
private string _name;
public partial string Name
{
get => _name;
set => _name = value;
}
}
Pour en savoir plus, consultez l’article sur les membres partiels.
Priorité de résolution de surcharge
En C# 13, le compilateur reconnaît l'OverloadResolutionPriorityAttribute pour préférer une surcharge à une autre. Les auteurs de bibliothèque peuvent utiliser cet attribut pour s’assurer qu’une nouvelle surcharge est préférable à une surcharge existante. Par exemple, vous pourriez ajouter une nouvelle surcharge plus efficace. Vous ne souhaitez pas interrompre le code existant qui utilise votre bibliothèque, mais vous souhaitez que les utilisateurs mettent à jour vers la nouvelle version lorsqu’ils recompilent. Vous pouvez utiliser la priorité de résolution de surcharge pour informer le compilateur de la surcharge à privilégier. Les surcharges avec la priorité la plus élevée sont privilégiées.
Cette fonctionnalité est destinée aux auteurs de bibliothèques pour éviter toute ambiguïté lors de l’ajout de nouvelles surcharges. Les auteurs de bibliothèque doivent faire preuve de prudence avec cet attribut pour éviter toute confusion.
Mot clé field
Le mot clé contextuel field
est en C# 13 comme fonctionnalité d’aperçu. Le jeton field
accède au champ de stockage synthétisé du compilateur dans un accesseur de propriété. Cela vous permet d’écrire un corps d’accesseur sans déclarer de champ de stockage explicite dans votre déclaration de type. Vous pouvez déclarer un corps pour un accesseur ou les deux accesseurs d’une propriété stockée dans un champ.
La fonctionnalité field
est publiée en préversion. Nous voulons apprendre de vos expériences à l’aide de celle-ci. Il existe un risque de changement cassant ou de confusion lors de la lecture de code dans les types qui incluent également un champ nommé field
. Vous pouvez utiliser @field
ou this.field
pour lever l’ambiguïté entre le mot clé field
et l’identificateur.
Important
Le mot clé field
est une fonctionnalité d’aperçu en C# 13. Vous devez utiliser .NET 9 et définir votre élément <LangVersion>
sur preview
dans votre fichier projet afin d’utiliser le mot clé contextuel field
.
Vous devez être prudent à l’aide de la fonctionnalité de mot clé field
dans une classe qui a un champ nommé field
. Le nouveau mot clé field
masque un champ nommé field
dans l’étendue d’un accesseur de propriété. Vous pouvez modifier le nom de la variable field
ou utiliser le jeton @
pour référencer l’identificateur field
en tant que @field
. Pour en savoir plus, lisez la spécification de fonctionnalité pour le mot clé field
.
Si vous essayez cette fonctionnalité et recevez des commentaires, ajoutez-les au problème lié à la fonctionnalité dans le référentiel csharplang
.