
Publié le 26/02/2025
Par Christophe MOMMER
Comme chaque année maintenant, les previews de la future version de .NET vont s'enchaîner et avec elles les nouveautés de notre langage favori : C# (d'ailleurs, si tu n'aimes pas C#, aucune raison de continuer à lire ce post).
La version 14 du langage devrait sortir avec la version 10 de .NET (oui, moi aussi je trouve ça perturbant et je pense qu'il faudrait essayer d'aligner les versions, quitte à faire des versions mineures du langage comme C# 7 pour arriver avec le même numéro de version ... mais c'est une autre histoire)
Qu'apporte la première preview du langage ? Découvrons ensemble !
Note : pour pouvoir tester ces nouveautés de votre côté, il faudra installer le dernier SDK de preview de .NET 10 et avoir l'IDE qui comprends les nouvelles syntaxes, typiquement VS Preview. Finalement, il faudra probablement activer la version preview
du langage dans votre csproj :
<LangVersion>preview</LangVersion>
- 1 : le mot-clé field -
Sûrement une des fonctionnalités les plus attendues, et pour cause ! Depuis longtemps, nous sommes habitués au propriétés automatiques. Le principe est simple : on utilise les mots-clés get
et set
, puis le compilateur fait le boulot à notre place pour générer le champ sous-jacent et l'utiliser dans le corps du get
et du set
de façon transparente. Cet ajout bienvenu permet de gagner en confort d'écriture par rapport aux propriétés complètes où il était nécessaire de faire le champ associé :
// propriété complète
private string _prenom;
public string Prenom
{
get => _prenom;
set => _prenom = value;
}
// propriété automatique
public string Prenom
{
get;
set;
}
On devait souvent utiliser la propriété complète si on avait une toute petite chose à faire (ah les bons vieux souvenir de WPF pour faire un RaisePropertyChanged
...).
Maintenant, c'est de l'histoire ancienne ! Nous avons dorénavant la possibilité de faire une semi-automatic property, c'est à dire de faire une propriété automatique tout en ayant la main sur le champ qui sera généré par le compilateur ! Cela passera pas l'usage du mot-clé field
:
public string Prenom
{
get;
set => field = value.Trim();
}
Pour ceux qui s'inquiète d'avoir déjà un champ privé (ou tout autre élément) appelé field dans son code : c'est devenu un mot-clé du langage, donc pour avoir un élément de code qui est similaire à un mot-clé du langage, on utilisera la même chose que ce qu'on a toujours faire pour y accéder : @
private string field;
public string Prenom
{
get;
set
{
field = value.Trim(); // utilisation du mot-clé
@field = value.Trim(); // utilisation du champ du même nom
}
}
Mais dans les faits, il vaut tout de même mieux éviter d'avoir des éléments de code qui reprennent le nom de mots-clés du langage ...
- 2 : amélioration du nameof -
L'opérateur nameof
a été une petite révolution à l'époque où nous faisions du WPF : plus de chaînes magiques et de possibilités de refactoring accrues ! Cet opérateur qui a vu le jour en C# 6 a tout de même dû attendre 8 versions (!!) avant d'évoluer sur sa prise en charge des types génériques pour fonctionner comme un typeof
.
Par exemple, avant, pour faire un nameof sur une List<T>
, il fallait qualifier le générique. Plus maintenant !
// avant C# 14
var name = nameof(List<int>);
// C# 14
var name = nameof(List<>);
// si plusieurs paramètres génériques
var name = nameof(Tuple<,,,>);
Voilà qui devrait clarifier le code !
- 3 : encore plus de conversion implicites vers Span<T> ! -
Le type Span<T>
est probablement l'apport dans .NET qui est le plus utilisé pour gagner en performances. Il existe des conversions implicites (c'est à dire transparente pour le développeur) entre Span<T>
et certaines collections, comme par exemple un tableau :
int[] data = { 1, 2, 3, 4, 5 };
// Il y a ici une conversion implicite
int sum = Sum(data);
int Sum(Span<int> data)
{
int sum = 0;
foreach (var item in data)
{
sum += item;
}
return sum;
}
C# 14 va encore plus loin (et ça va nous offrir des gains de performances sans effort, une recompilation suffira), comme par exemple avec la gestion des méthodes d'extension :
int[] data = { 1, 2, 3, 4, 5 };
// conversion implicite du compilateur, plus besoin de faire un AsSpan
int sum = data.SumInts();
static class SpanExt
{
public static int SumInts(this Span<int> data)
{
int sum = 0;
foreach (var item in data)
{
sum += item;
}
return sum;
}
}
A noter que même avec la preview 1 de VS 17.14, des erreurs sont marquées dans l'éditeur de code, mais le code compile bien en preview (alors qu'il ne compilera pas en version 13 du langage)
- 4 : amélioration des parmètres de lambda -
Les lambdas sont pratiques dans bien des situations. Avec l'expension des minimal APIs, elles sont devenues une "first class citizen" du développement en .NET. Cependant, les lambdas à la base étaient pensées pour être simples et pas remplacer à 100% une fonction. Cette différence s'efface au fur et à mesure des versions de C#, et dans la version 14, certains mots-clés de paramètres sont dorénavant disponibles pour les paramètres de lambda :
TryParse<int> tryParse = (text, out result) => Int32.TryParse(text, out result);
var p = new Person { Name = "Christophe" };
DisplayName displayName = (in p) => p.Name;
class Person
{
public string Name { get; set; }
}
delegate bool TryParse<T>(string text, out T result);
delegate string DisplayName(in Person p);
A noter que même avec la preview 1 de VS 17.14, des erreurs sont marquées dans l'éditeur de code, mais le code compile bien en preview (alors qu'il ne compilera pas en version 13 du langage)
En conclusion, comme souvent, certains ajouts du langage vont avoir un impact direct sur notre développement au quotidien (je pense au 2 premiers points) alors que d'autres seront transparents et sont surtout à destination des équipes du framework pour nous livrer encore une fois un excellent cru en termes de performances et de simplicité d'usage (et là, je pense aux deux derniers points)