C# – Initialisation tardive des propriétés (lazy)

Présentation

Afin d’améliorer les performances et la gestion de la mémoire lors de la création d’objets, il est parfois nécessaire d’initialiser certaines de leurs propriétés de manière tardive, c’est-à-dire au moment où nous souhaitons les utiliser.

Par exemple, lors de l’instanciation de la classe Report, la collection d’objets de type Statistic est coûteuse en mémoire et en performance, alors que ces statistiques sont nécessaires uniquement lors de la génération d’un rapport dans un fichier au format Json.

Implémentation de la propriété

Voici l’implémentation de la classe Statistic :

public class Statistic
{
    public Statistic(string aCode)
    {
        // Simulation d’un traitement.
        Thread.Sleep(3000);
    }
}

Et l’implémentation de la classe Report :

public class Report
{
    public List<Statistic> Statistics { get; set; }

    public Report()
    {
        this.Statistics = new List<Statistic>()
        {
            new Statistic("A25"),
            new Statistic("T23"),
            new Statistic("U87")
        };
    }

    public void Export(string aPathFile)
    {
        List<Statistic> statistics = this.Statistics;

        // Génération du rapport...
    }
}

Pour le moment, les statistiques sont initialisées dans le constructeur, ce qui impacte la creation d’un rapport. L’implémentation de la classe Program permet de générer un rapport :

using LazyProperties;
using Microsoft.Extensions.Hosting;
using System.Diagnostics;

IHostBuilder? host = Host.CreateDefaultBuilder(args);

Stopwatch stopwatch = Stopwatch.StartNew();
stopwatch.Start();

Report report = new Report();

Console.WriteLine($"Temps d'exécution : {stopwatch.Elapsed.TotalSeconds} s");
stopwatch.Restart();

report.Export(@"c:\exports\report.json");

stopwatch.Stop();
Console.WriteLine($"Temps d'exécution : {stopwatch.Elapsed.TotalSeconds} s");

host.Build().Run();

Le résultat de son execution est le suivant :

  • Temps d’exécution : 9,0392403 s
  • Temps d’exécution : 0,0001059 s

En définissant la propriété Statistics de la classe Report en tant que propriété “lazy” :

public class Report
{
    public Lazy<List<Statistic>> Statistics { get; set; }

    public Report()
    {
        this.Statistics = new Lazy<List<Statistic>>(() => new List<Statistic>()
        {
            new Statistic("A25"),
            new Statistic("T23"),
            new Statistic("U87")
        });
    }

    public void Export(string aPathFile)
    {
        List<Statistic> statistics = this.Statistics.Value;

        // Génération du rapport...
    }
}

La liste des statistiques est initialisée via un délégué. Les temps d’exécution sont les suivants :

  • Temps d’exécution : 0,0004351 s
  • Temps d’exécution : 9,0113186 s

Les différences entre les temps d’exécution montrent que l’initialisation de la propriété “lazy” est réalisée lors de l’utilisation de la propriété et non lors de l’instanciation de la classe Report. Important : le délégué permettant d’initialiser la propriété “lazy” n’est exécutée qu’une seule fois, lors du premier accès à cette propriété.

Étiquettes :

About: James RAVAILLE

Travaillant avec la plateforme Microsoft .NET depuis 2002, j'alterne les missions de formation et d'ingénierie avec cette plateforme. J'écris ce blog pour transmettre mes connaissances à tout développeur, qu'il soit débutant ou expérimenté.