缓存属性vs Lazy <T>

Mar*_*erl 50 .net c# lazy-loading .net-4.0

在.NET 4中,还可以使用System.Lazy<T>该类编写具有缓存属性的以下代码段.我测量了两种方法的性能,它几乎是一样的.对于为什么我应该使用一个而不是另一个,是否有任何真正的好处或魔力?

缓存属性

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

懒惰<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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 71

我会Lazy<T>一般地使用:

  • 它是线程安全的(在这种情况下可能不是问题,但在其他情况下可能会出现问题)
  • 它显而易见的是,这个名字正在发生什么
  • 它允许null为有效值

请注意,您不具备使用lambda表达式的委托.例如,这是一种可能稍微清洁的方法:

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

当创建过程变得复杂时,这尤其方便.请注意,通过它的外观,您可以GradientStops在创建代码中使用集合初始值设定项.

另一个选择是不要懒惰,当然......除非你的类中有几个这样的属性而你只想逐个创建相关的对象,你可以依赖懒惰的类初始化的情况.

正如DoubleDown的回答所指出的那样,没有办法重置这个以强制重新计算(除非你让Lazy<T>字段不是只读) - 但我很少发现它很重要.

  • @ user256034:当你不使用.NET 4时:) (14认同)

Ode*_*ded 7

使用Lazy<T>,因为它表达你正在做的事情 - 延迟加载.

此外,它保持您的财产非常干净,并且是线程安全的.