C# 13 : Découvrez les dernières fonctionnalités en avant-première, dont l'amélioration de la collection params et la résolution des surcharges, ainsi que l'ajout des propriétés partielles

Voici l'état actuel de ce que vous pouvez essayer dans C# 13, ainsi que les mises à jour sur les fonctionnalités prévues pour cette version et au-delà.

Selon une l'équipe de Microsoft en charge, C# 13 commence à prendre forme avec des fonctionnalités axées sur la flexibilité, les performances et l'amélioration des fonctionnalités pour une utilisation quotidienne. C# est construit de manière ouverte et lors de la Microsoft Build, Microsoft a donné un aperçu de ce qui allait arriver dans C# 13.

Vous pouvez trouver les derniers aperçus de C# 13 dans le dernier aperçu de .NET 9 (depuis l'aperçu 6) et dans le dernier aperçu de Visual Studio 2022-17.11. Pour accéder aux fonctionnalités de prévisualisation, définissez votre version de langue sur preview dans votre fichier de projet :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
      <!--other settings-->
      <LangVersion>preview</LangVersion>
      <!--other settings-->
   </PropertyGroup>
</Project>

Présentation rapide des mise à jour et des nouvelles fonctionnalités :

  • Amélioration de la collection de paramètres pour une plus grande flexibilité
  • Objet de verrouillage
  • Amélioration de l'opérateur d'indexation
  • Séquence d'échappement \e
  • Propriétés partielles
  • Amélioration des types naturels de groupes de méthodes
  • ref et unsafe dans les méthodes asynchrones et les itérateurs
  • Mise à jour sur les types d'extension



Collections params

C# 13 étend params à tout type pouvant être construit via une expression de collection. Cela ajoute de la flexibilité, que vous écriviez une méthode ou que vous l'appeliez.

Lorsque le mot-clé params apparaît devant un paramètre, les appels à la méthode peuvent fournir une liste délimitée par des virgules de zéro ou plusieurs valeurs. Ce qui suit fonctionne dans toutes les versions de C# :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
public void WriteNames(params string[] names)
   => Console.WriteLine(String.Join(", ", names));
 
WriteNames("Mads", "Dustin", "Kathleen");
WriteNames(new string[] {"Mads", "Dustin", "Kathleen"});
// Both of these Would output: Mads, Dustin, Kathleen
Notez que vous pouvez appeler la méthode avec une liste de valeurs délimitée par des virgules ou avec un objet du type sous-jacent.

À partir de C# 13, les paramètres params peuvent être de n'importe quel type pris en charge pour les expressions de collection. Par exemple :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
public void WriteNames(params List<string> names)
   => Console.WriteLine(String.Join(", ", names));
Lorsque vous appelez une méthode dont le paramètre est un IEnumerable<T>, vous pouvez transmettre les résultats d'une expression LINQ. Si le paramètre IEnumerable<T> possède le modificateur params, vous pouvez également transmettre une liste délimitée par des virgules. Vous pouvez utiliser une liste délimitée par des virgules lorsque vous avez des constantes et une expression LINQ lorsque vous en avez besoin :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void WriteNames(params IEnumerable<string> names)
   => Console.WriteLine(String.Join(", ", names));
 
var persons = new List<Person>
{
   new Person("Mads", "Torgersen"),
   new Person("Dustin", "Campbell"),
   new Person("Kathleen", "Dollard")
};
 
// All of the following output: Mads, Dustin, Kathleen
WriteNames("Mads", "Dustin", "Kathleen");
WriteNames(persons.Select(person => person.FirstName));
WriteNames(from p in persons select p.FirstName);


Résolution des surcharges

Lors de la création d'une méthode, vous pouvez fournir plusieurs surcharges de params. Par exemple, l'ajout d'une surcharge IEnumerable<T> prend en charge LINQ et l'ajout d'une surcharge ReadOnlySpan<T> ou Span<T> réduit les allocations, ce qui peut améliorer les performances.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
public void WriteNames(params string[] names)
   => Console.WriteLine(String.Join(", ", names));
 
public void WriteNames(params ReadOnlySpan<string> names)
   => Console.WriteLine(String.Join(", ", names));
 
public void WriteNames(params IEnumerable<string> names)
   => Console.WriteLine(String.Join(", ", names));
Lorsque l'un des types spécifiés est transmis, cette surcharge est utilisée. Lorsque des valeurs délimitées par des virgules ou aucune valeur sont transmises, la meilleure surcharge est sélectionnée. En utilisant les surcharges ci-dessus :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
// IEnumerable overload is used
WriteNames(persons.Select(person => person.FirstName)); 
 
// array overload is used
WriteNames(new string[] {"Mads", "Dustin", "Kathleen"}); 
 
// most efficient overload is used: currently ReadOnlySpan
WriteNames("Mads", "Dustin", "Kathleen");
Les surcharges multiples peuvent être plus pratiques et améliorer les performances. Les auteurs de bibliothèques doivent donner à toutes les surcharges la même sémantique afin que les appelants n'aient pas à se préoccuper de savoir quelle surcharge est utilisée.


Objet lock

.NET 9 inclut un nouveau type System.Threading.Lock pour l'exclusion mutuelle qui peut être plus efficace que le verrouillage sur une instance System.Object arbitraire. La proposition de type System.Threading.Lock contient plus d'informations sur ce type et sur les raisons de sa création. Au fil du temps, ce type devrait devenir le mécanisme principal utilisé pour la plupart des verrouillages dans le code C#.

C# 13 facilite l'utilisation de ce type. Lorsque le compilateur reconnaît que la cible de l'instruction lock est un objet System.Threading.Lock, C# génère désormais des appels à l'API System.Threading.Lock et fournit des avertissements pour les cas où une instance d'un Lock pourrait être traitée de manière incorrecte comme un object normal.

Cette mise à jour signifie que la syntaxe familière de l'instruction de véroullage tire parti des nouvelles fonctionnalités du runtime. Un code familier s'améliore avec un minimum de changements. Il suffit de changer le TargetFramework de votre projet en .NET 9 et de changer le type du verrou d'objet en System.Threading.Lock :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MyClass 
{
    private object myLock = new object();
 
    public void MyMethod() 
    {
        lock (myLock)
        {
           // Your code
        }          
    }
}
 
public class MyClass 
{
    // The following line is the only change
    private System.Threading.Lock myLock = new System.Threading.Lock();
 
    public void MyMethod() 
    {
        lock (myLock)
        {
            // Your code
        }     
    }
}


Index à partir de la fin dans les initialisateurs

L'opérateur d'indexation ^ permet d'indiquer une position dans une collection dénombrable par rapport à la fin de la collection. Il fonctionne désormais dans les initialisateurs :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Program
{ 
    static void Main()
    {
        var x = new Numbers
        {
            Values = 
            {
                [1] = 111,
                [^1] = 999  // Works starting in C# 13
            }
            // x.Values[1] is 111
            // x.Values[9] is 999, since it is the last element
        };
    }
}
 
class Numbers
{
    public int[] Values { get; set; } = new int[10];
}


Séquence d'échappement \e

C# 13 introduit une nouvelle séquence d'échappement pour le caractère que vous connaissez sous le nom de ESCAPE ou ESC. Auparavant, vous deviez taper ce caractère sous la forme d'une variante de \u001b. Cette nouvelle séquence est particulièrement pratique pour interagir avec des terminaux utilisant les codes d'échappement VT100/ANSI de System.Console. Par exemple :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
// Prior to C# 13
Console.WriteLine("\u001b[1mThis is a bold text\u001b[0m");
 
// With C# 13
Console.WriteLine("\e[1mThis is a bold text\e[0m");
La création d'une sortie de terminal fantaisiste est plus facile et moins sujette aux erreurs.


Propriétés partielles

C# 13 ajoute les propriétés partielles. Tout comme les méthodes partielles, leur objectif principal est de prendre en charge les générateurs de sources. Les méthodes partielles sont disponibles depuis de nombreuses versions et ont été améliorées en C# 9. Les propriétés partielles ressemblent beaucoup à leurs homologues de méthodes partielles.

Par exemple, à partir de .NET 7 (C# 12), le générateur de source d'expressions régulières crée un code efficace pour les méthodes :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
[GeneratedRegex("abc|def")]
private static partial Regex AbcOrDefMethod();
 
if (AbcOrDefMethod().IsMatch(text))
{
   // Take action with matching text
}
Dans .NET 9 (C# 13), le générateur de source Regex a été mis à jour et si vous préférez utiliser une propriété, vous pouvez également utiliser :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
[GeneratedRegex("abc|def")]
private static partial Regex AbcOrDefProperty { get; };
 
if (AbcOrDefProperty.IsMatch(text))
{
   // Take action with matching text
}
Les propriétés partielles permettront aux concepteurs de générateurs de sources de créer plus facilement des API naturelles.

Amélioration du type naturel des groupes de méthodes

Le type naturel d'une expression est le type déterminé par le compilateur, par exemple lorsque le type est assigné à var ou Delegate. C'est simple lorsqu'il s'agit d'un type simple. En C# 10, ils ont ajouté la prise en charge des groupes de méthodes. Les groupes de méthodes sont utilisés lorsque vous incluez le nom d'une méthode sans parenthèses dans un délégué :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
Todo GetTodo() => new(Id: 0, Name: "Name");
var f = GetTodo; // the type of f is Func<ToDo>
C# 13 affine les règles de détermination du type naturel afin de prendre en compte les candidats en fonction de leur portée et d'élaguer les candidats qui n'ont aucune chance de réussir. La mise à jour de ces règles permettra de réduire les erreurs du compilateur lors de l'utilisation de groupes de méthodes.


allows ref struct
C# 13 ajoute une nouvelle façon de spécifier les capacités pour les paramètres de type générique. Par défaut, les paramètres de type ne peuvent pas être ref struct. C# 13 vous permet de spécifier qu'un paramètre de type peut être une ref struct et applique les règles appropriées. Alors que d'autres contraintes génériques limitent l'ensemble des types pouvant être utilisés comme paramètre de type, cette nouvelle spécification élargit les types autorisés. Nous considérons qu'il s'agit d'une anti-contrainte puisqu'elle supprime plutôt qu'elle n'ajoute une restriction. La syntaxe allows ref struct dans la clause where, où allows indique cette expansion de l'usage :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
T Identity<T>(T p)
    where T : allows ref struct
    => p;
 
// Okay
Span<int> local = Identity(new Span<int>(new int[10]));
Un paramètre de type spécifié avec allows ref struct a tous les comportements et restrictions d'un type ref struct.



ref et unsafe dans les méthodes async et les itérateurs

Avant C# 13, les méthodes itératrices (méthodes qui utilisent yield return) et les méthodes async ne pouvaient pas déclarer de variables locales ref, ni avoir un contexte unsafe.

En C# 13, les méthodes async peuvent déclarer des variables locales ref ou des variables locales de type ref struct. Ces variables ne peuvent pas être conservées au-delà d'une limite await ou d'une limite yield return.

De la même manière, C# 13 autorise les contextes unsafe dans les méthodes d'itérateur. Cependant, toutes les instructions yield return et await doivent être dans des contextes sûrs. Ces restrictions assouplies vous permettent d'utiliser les variables locales ref et les types ref struct dans un plus grand nombre d'endroits.

Une mise à jour sur les types d'extension sera disponibles dans les premiers aperçus de C# 14 (NET 10).

Source : Annonce C# 13

Et vous ?

Quel est votre avis sur le sujet ?

Voir aussi :

Annonces et mises à jour de .NET à la Microsoft Build 2024 : intégration profonde de l'IA, simplification du développement-natif avec .Net Aspire, ainsi que des améliorations des fonctionnalités C# pour C# 13

Microsoft partage sa vision initiale de .NET 9 et publie le premier aperçu de la nouvelle version du framework, dont les domaines d'intérêt sont le développement d'apps cloud-natives et intelligentes

Microsoft annonce C# 12 : une meilleure productivité des développeurs avec une syntaxe simplifiée et une exécution plus rapide