C# 10

c sharp logo

C# 10 est disponible depuis novembre 2021. Dans ce blogue, je reviens sur quelques-unes des nouvelles fonctionnalités que ça nous a apporté, en complément au dernier vidéo de la chaîne. Bonne lecture!

Tout d’abord en rappel, la vidéo que nous avons publié la semaine passée pour démontrer certaines des nouveautés de C# 10:

Usings implicites

Les usings implicites sont là pour nous permettre d’avoir une meilleure visibilité au niveau de nos classes, en faisant un import automatique de tout ce qui fait parti du framework utilisé dans notre projet. Par exemple, les librairies faisant parti de Microsoft.NET.Sdk pour un projet console seront automatiquement importées et nous n’aurons plus besoin des les importer dans nos classes. Pour voir la liste des namespaces inclus pour les différents SDK, vous pouvez consulter cet article.

On peut aussi spécifier manuellement certaines exclusions, par exemple si le nom d’une classe entrerait en conflit avec une classe de notre projet. Pour faire ceci, il suffit d’ajouter un ItemGroup dans notre fichier de projet et y inclure l’élément Using avec l’attribut correspondant à notre besoin:

Usings globaux

Les usings globaux se veulent un complément aux usings implicites. En préfixant un using du mot clé global, on se retrouve à importer ce namespace pour tout notre projet. Mon exemple préféré pour cette utilisation est au niveau de nos projets de tests. Toutes nos classes de tests vont contenir certains usings qui reviennent systématiquement. Par contre, en ajoutant un fichier qui contiendra ceci:

global using FluentAssertions;
global using Moq;
global using Xunit;

On vient éliminer ces 3 imports de tous nos fichiers du projet. Lorsqu’on parlait de lisibilité améliorée, ceci vient enlever le « bruit » que ces 3 lignes font dans chacune de ces classes.

File-scoped namespaces

Une autre fonctionnalité intéressante que C# 10 nous amène est la possibilité d’avoir des namespaces à portée unique pour notre fichier. Donc au lieu d’avoir un namespace avec accolades, qui amène un niveau d’indentation à tout ce qui se trouve à l’intérieur, on se retrouve plutôt avec ceci:

namespace CSharp10;

public class Person
{
    public Guid Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public Address Address { get; set; } = new Address();
}

On gagne donc une meilleure utilisation de l’espace horizontal en réduisant l’indentation de nos fichiers et une meilleure lisibilité.

Types naturels pour lambdas

Avant C# 10, déclarer une lambda impliquait de définir son type complet, par exemple Func<string, int>. Maintenant l’inférence du type est possible donc on peut simplement déclarer notre lambda avec le mot clé var. On peut aussi appliquer la même utilisation sur une méthode sans paramètres, si celle-ci n’a pas plusieurs overloads. Donc ceci devient quelque chose de possible à faire:

var read = Console.Read;

Structures

Pour ce qui est des structures, un des plus gros changements est le fait qu’on peut maintenant en avoir de type record. Cela apporte plusieurs aspects intéressants. Le premier, c’est qu’on peut déclarer une structure de manière positionnelle, comme ceci:

public readonly record struct Point(double X, double Y);

Une autre chose à remarquer dans cette déclaration, c’est l’utilisation du mot-clé readonly. Dans le contexte d’une structure, ceci aura pour effet de créer les propriétés pour qu’elles soit immuables, de la même manière que si on avait déclaré la propriété avec get et init. Si on préfère la version longue, on peut aussi le faire via une déclaration plus conventionnelle, puisqu’on peut maintenant avoir un constructeur vide et une initialisation sur les propriétés:

public record struct Point
{
    public Point()
    {        
    }

    public Point(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; init; } = 0;
    public double Y { get; init; } = 0;
}

Expressions with sur types anonymes

Il est maintenant possible d’utiliser les expressions with sur des types anonymes, de la même manière que sur un record. Avec ceci, ce code nous permet de plus facilement déclarer de nouvelles variables lorsqu’on travaille avec des types anonymes:

var person = new
{
    Age = 1,
    Name = "Test"
};
var person2 = person with { Age = 2 };

Améliorations aux string interpolées

Une amélioration qui semble petite, mais qui risque de nous faciliter grandement la vie est au niveau des interpolated string. Il est maintenant possible de déclarer des constantes interpolées, versus avant qu’on pouvait uniquement sur une variable. Cela peut par exemple nous permettre de déclarer des constantes pour nos routes d’api:

public static class ApiRoutes
{
    private const string BasePath = "/api";
    public const string WeatherForecast = $"{BasePath}/forecast";
}

Ou encore d’utiliser directement le nom d’une classe avec nameof dans des attributs, comme ceci:

[Obsolete($"Use {nameof(NewEntity)} instead")]

Conclusion

Comme pour la vidéo, ceci n’était qu’un résumé de quelques-unes des nouvelles fonctionnalités de C# 10. Nous n’avons pas parlé des static abstract members qui sont disponibles en preview, qui risquent de devenir une fonctionnalité très intéressante dans le future de C#. Pour la liste complète des changements, n’hésitez pas à consulter la documentation à ce sujet.

Dans votre utilisation quotidienne, quelle est LA fonctionnalité qui vous intéresse le plus de C# 10? Et est-ce qu’il y a un aspect que vous aimeriez voir abordé plus en détails, soit dans un nouveau blogue ou vidéo? N’hésitez pas à me laisser savoir dans les commentaires!

Bruno

Auteur : Bruno

De jour, je suis développeur, chef d'équipe et le co-animateur du Bracket Show. De soir, je suis un mari et le père de deux magnifiques enfants. Le temps qu'il me reste après tout cela, je le passe à tenter de bouger, à jouer et écrire des critiques de jeux vidéos, ainsi qu'à préparer du matériel pour les enregistrements du Bracket Show et pour ce blog. Au travers tout cela, je suis aussi passionné de musique et de microbrasseries.