Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 缓存属性与惰性<;T>;_C#_.net_.net 4.0_Lazy Loading - Fatal编程技术网

C# 缓存属性与惰性<;T>;

C# 缓存属性与惰性<;T>;,c#,.net,.net-4.0,lazy-loading,C#,.net,.net 4.0,Lazy Loading,在.NET4中,还可以使用该类编写以下具有缓存属性的代码段。我测量了两种方法的性能,结果几乎相同。为什么我应该使用一个而不是另一个,这有什么真正的好处或魔力吗 缓存属性 public static class Brushes { private static LinearGradientBrush _myBrush; public static LinearGradientBrush MyBrush { get {

在.NET4中,还可以使用该类编写以下具有缓存属性的代码段。我测量了两种方法的性能,结果几乎相同。为什么我应该使用一个而不是另一个,这有什么真正的好处或魔力吗

缓存属性

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;
        }
    }
}
懒惰

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;
        }
    }
}
公共静态类笔刷
{
私有静态只读惰性\u myBrush=
新懒惰(()=>
{
var linearGradientBrush=新的linearGradientBrush{…};
linearGradientBrush.GradientStops.Add(…);
linearGradientBrush.GradientStops.Add(…);
返回线ArgRadientBrush;
}
);
公共静态线ArgRadientBrush MyBrush
{
获取{return\u myBrush.Value;}
}
}
懒惰的
更简单,它清楚地表达了代码的意图。
它也是线程安全的

请注意,如果您在多个线程上实际使用此功能,则需要将其设置为
[ThreadStatic]
;GDI+对象不能在线程之间共享。

惰性
将正确处理并发场景(如果您传入了正确的),而您的示例没有任何线程安全检查。

使用
惰性
,因为它准确地表达了您正在做的事情-惰性加载

此外,它可以保持您的属性非常干净,并且是线程安全的。

我通常会使用
Lazy

  • 它是线程安全的(在这种情况下可能不是问题,但在其他情况下可能是)
  • 只凭名字就能清楚地知道发生了什么
  • 它允许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; }
    }
}
公共静态类笔刷
{
私有静态只读惰性\u myBrush=
新的Lazy(CreateMyBrush);
私有静态LinearGradientBrush CreateMyBrush()
{
var linearGradientBrush=新的linearGradientBrush{…};
linearGradientBrush.GradientStops.Add(…);
linearGradientBrush.GradientStops.Add(…);
返回线ArgRadientBrush;
}
公共静态线ArgRadientBrush MyBrush
{
获取{return\u myBrush.Value;}
}
}
当创建过程因循环等而变得复杂时,这尤其方便。请注意,从外观上看,您可以在创建代码中为
GradientStops
使用集合初始值设定项

当然,另一个选择是不要懒洋洋地这么做。。。除非您的类中有几个这样的属性,并且您只希望逐个创建相关对象,否则在许多情况下都可以依赖惰性类初始化


正如DoubleDown的回答中所指出的,没有办法重置它以强制重新计算(除非您使
惰性
字段不是只读的)-但我很少发现这一点很重要。

如果您的性能大致相同,那么在缓存版本上使用
Lazy
的唯一原因就是您不确定用户是否真的要加载属性


懒惰的要点是等待用户需要资源,然后及时在该实例中创建它。如果他们总是需要使用资源,那么使用
Lazy
是没有意义的,除非您需要它的一些其他用途,例如它是线程安全的。

通常不使用Lazy的唯一原因是将变量重置为null,以便下次访问时再次加载它。Lazy没有重置,您需要从头开始重新创建Lazy。

Lazy有一些同步开销来提供线程安全性,而缓存属性是在任何其他代码之前通过CLR方式初始化的,您不需要支付同步成本

从可测试性的角度来看,Lazy是经过良好测试和验证的工件


然而,在我看来,与其他选项相比,使用
Lazy
编写自己的实现的开销非常小。(当然,这是一种很好的方式。)有趣的是,我倾向于说它的代码更少,可读性更强,但您的示例表明情况并非如此。但是,我已经有了一个支持此行为和更常见的支持字段行为的支持字段的
属性
类。Lazy允许线程安全在什么情况下使用Lazy是一个问题?@user256034:当您不使用.NET 4:)谢谢!您列表中的3点正是我要搜索的;)好的点数列表,如果你同意“双解”的答案,并且会考虑把他们的观点加在你的答案上,我会赞成:“TSEMER:这不是我个人认为有用的东西,但是我增加了一个小音符。看这个答案好点!IMHO,这与@JonSkeet的答案结合起来就是完整答案。-1,OP的替代方案是相同的,因为如果从未调用属性,那么列表就永远不会实例化。从这个意义上说,他们都是“懒惰的”。