54 votes

Propriété en cache contre Lazy<T>

Dans .NET 4, l'extrait suivant avec une propriété en cache peut également être écrit à l'aide de la commande System.Lazy<T> classe. J'ai mesuré les performances des deux approches et c'est à peu près la même chose. Y a-t-il un avantage réel ou une raison magique pour laquelle je devrais utiliser l'une plutôt que l'autre ?

Propriété cachée

public static class Brushes
{
    private static LinearGradientBrush _myBrush;

    public static LinearGradientBrush MyBrush
    {
        get
        {
            if (_myBrush == null)
            {
                var linearGradientBrush = new LinearGradientBrush { ...};
                linearGradientBrush.GradientStops.Add( ... );
                linearGradientBrush.GradientStops.Add( ... );

                _myBrush = linearGradientBrush;
            }

            return _myBrush;
        }
    }
}

Lazy<T>

public static class Brushes
{
    private static readonly Lazy<LinearGradientBrush> _myBrush =
        new Lazy<LinearGradientBrush>(() =>
            {
                var linearGradientBrush = new LinearGradientBrush { ...};
                linearGradientBrush.GradientStops.Add( ... );
                linearGradientBrush.GradientStops.Add( ... );

                return linearGradientBrush;
            }
        );

    public static LinearGradientBrush MyBrush
    {
        get { return _myBrush.Value; }
    }
}

75voto

Jon Skeet Points 692016

J'utiliserais Lazy<T> en général :

  • Il est thread-safe (ce n'est peut-être pas un problème dans ce cas, mais ce le serait dans d'autres).
  • Il est évident que ce qui se passe juste par le nom.
  • Il permet à null d'être une valeur valide

Notez que vous ne devez pas ont pour utiliser une expression lambda pour le délégué. Par exemple, voici une approche qui peut être légèrement plus propre :

public static class Brushes
{
    private static readonly Lazy<LinearGradientBrush> _myBrush =
        new Lazy<LinearGradientBrush>(CreateMyBrush);

    private static LinearGradientBrush CreateMyBrush()
    {
        var linearGradientBrush = new LinearGradientBrush { ...};
        linearGradientBrush.GradientStops.Add( ... );
        linearGradientBrush.GradientStops.Add( ... );

        return linearGradientBrush;
    }

    public static LinearGradientBrush MyBrush
    {
        get { return _myBrush.Value; }
    }
}

C'est particulièrement pratique lorsque le processus de création se complique avec des boucles, etc. Notez qu'à première vue, vous pourriez utiliser un initialisateur de collection pour les éléments suivants GradientStops dans votre code de création.

Une autre option est pas pour faire cela paresseusement, bien sûr... à moins que vous n'ayez plusieurs propriétés de ce type dans votre classe et que vous ne vouliez créer les objets pertinents qu'un par un, vous pourriez vous reposer sur l'initialisation paresseuse de la classe dans de nombreuses situations.

7voto

Oded Points 271275

Utilisez Lazy<T> car il exprime exactement ce que vous faites - un chargement paresseux.

En outre, elle permet de garder votre propriété très propre et est sans danger pour les fils.

4voto

Double Down Points 698

En général, la seule raison de ne pas utiliser lazy est de réinitialiser la variable à null afin que le prochain accès la charge à nouveau. Lazy n'a pas de réinitialisation et vous devrez recréer la lazy à partir de zéro.

2voto

marcind Points 38002

Lazy<T> gérera correctement les scénarios simultanés (si vous passez dans le bon fichier LazyThreadSafetyMode ) alors que votre exemple ne comporte aucune vérification de la sécurité des fils.

1voto

SLaks Points 391154

Le site Lazy<T> est plus simple - elle exprime clairement l'intention du code.
Il est également sans risque pour les fils.

Notez que si vous utilisez cette fonction sur plusieurs fils, vous devez la rendre [ThreadStatic] ; les objets GDI+ ne peuvent pas être partagés entre plusieurs threads.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X