Trois nouvelles fonctionnalités de C# 12 en aperçu

Par:
fredericmazue

ven, 14/04/2023 - 12:35

Microsoft a présenté trois nouvelles fonctionnalits en aperçu (preview), pour C# 12. Cet fonctionnalités peuvent être testées via la dernière préversion de Visual Studio 17.6, ou la dernière préversion de .NET 8. Ces trois nouvelles fonctionnalités sont :

  • Constructeurs principaux pour les classes et les structures sans enregistrement
  • Des directives Using pour n'importe quel type
  • Valeurs par défaut pour les expressions lambda

Constructeurs principaux pour les classes et les structures sans enregistrement

Les constructeurs principaux vous permettent d'ajouter des paramètres à la déclaration de classe elle-même et d'utiliser ces valeurs dans le corps de la classe. Par exemple, vous pouvez utiliser les paramètres pour initialiser les propriétés ou dans le code des méthodes et des accesseurs de propriétés. Des constructeurs principaux ont été introduits pour les enregistrements en C# 9 dans le cadre de la syntaxe positionnelle des enregistrements. C# 12 les étend à toutes les classes et structures.

La syntaxe et l'utilisation de base d'un constructeur principal sont :

public class Student(int id, string name, IEnumerable<decimal> grades)
{
    public Student(int id, string name) : this(id, name, Enumerable.Empty<decimal>()) { }
    public int Id => id;
    public string Name { get; set; } = name.Trim();
    public decimal GPA => grades.Any() ? grades.Average() : 4.0m;
}

Les principaux paramètres du constructeur de la classe d'exemple Student ci-dessus sont disponibles dans tout le corps de la classe. Une façon de les utiliser consiste à initialiser les propriétés. Contrairement aux enregistrements, les propriétés ne sont pas automatiquement créées pour les paramètres du constructeur principal dans les classes et les structures non enregistrées. Les classes et les structures sans enregistrement ont souvent plus de complexité que les enregistrements, par conséquent, ils ont souvent besoin de paramètres de constructeur qui ne doivent pas être exposés. La création explicite de propriétés permet de savoir quelles données sont exposées, conformément à l'utilisation courante des classes. Les constructeurs principaux permettent d'éviter le passe-partout consistant à déclarer des champs privés et à avoir des corps de constructeur triviaux affectant des valeurs de paramètre à ces champs.

Directives Using pour n'importe quel type

C# 12 étend l'utilisation de la prise en charge des directives using à n'importe quel type. Voici quelques exemples:

using Measurement = (string, int);
using PathOfPoints = int[];
using DatabaseInt = int?;

Vous pouvez désormais alias presque n'importe quel type. Vous pouvez créer un alias de types valeur nullable, bien que vous ne puissiez pas créer un alias de types référence nullable. Les tuples sont particulièrement intéressants car vous pouvez inclure des noms et des types d'éléments :

using Measurement = (string Units, int Distance);

Vous pouvez utiliser des alias partout où vous utiliseriez un type. Par exemple:

public void F(Measurement x)
{ }

Les types d'alias vous permettent d'abstraire les types réels que vous utilisez et vous permettent de donner des noms conviviaux aux noms génériques confus ou longs. Cela peut faciliter la lecture de votre code.

Valeurs par défaut pour les expressions lambda

C# 12 franchit, selon les termes de Miccrosoft, une nouvelle étape dans l'autonomisation des expressions lambda en permettant de spécifier des valeurs par défaut pour les paramètres. La syntaxe est la même que pour les autres paramètres par défaut :

var addWithDefault = (int addTo = 2) => addTo + 1;
addWithDefault(); // 3
addWithDefault(5); // 6

Semblable aux autres valeurs par défaut, la valeur par défaut des expressions lambda sera émise dans les métadonnées et est disponible via la réflexion en tant que DefaultValue de ParameterInfo de la propriété Method de l'expression lambda. Par exemple:

var addWithDefault = (int addTo = 2) => addTo + 1;
addWithDefault.Method.GetParameters()[0].DefaultValue; // 2