簡體   English   中英

緩存屬性vs Lazy <T>

[英]Cached property vs Lazy<T>

在.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;
        }
    }
}

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

我會一般使用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; }
    }
}

當創建過程變得復雜時,這尤其方便。請注意,通過它的外觀,您可以在創建代碼中使用GradientStops的集合初始值設定項。

另一個選擇是不要懶惰,當然......除非你的類中有幾個這樣的屬性而你只想逐個創建相關的對象,你可以依賴懶惰的類初始化的情況。

正如DoubleDown的回答所指出的,沒有辦法重置它來強制重新計算(除非你讓Lazy<T>字段不是只讀) - 但我很少發現這很重要。

使用Lazy<T> ,因為它表達了你正在做的事情 - 延遲加載。

此外,它保持您的財產非常干凈,並且是線程安全的。

通常,不使用lazy的唯一原因是將變量重置為null,以便下一次訪問使其再次加載。 懶惰沒有重置,你需要從頭開始重新創建懶惰。

Lazy<T>將正確處理並發場景(如果傳入正確的LazyThreadSafetyMode ),而您的示例沒有任何線程安全檢查。

Lazy<T>更簡單 - 它清楚地表達了代碼的意圖。
它也是線程安全的。

請注意,如果您實際上在多個線程上使用它,則需要將其設置為[ThreadStatic] ; GDI +對象不能跨線程共享。

Lazy有一些同步化開銷來提供線程安全性,而緩存屬性在任何其他代碼之前通過CLR方式初始化,並且您不需要支付同步成本

從可測試性的角度來看,Lazy經過了充分的測試和驗證。

但是,在我看來,它有一個非常輕微的開銷,而不是其他選擇

好吧,如果你的性能大致相同,那么在緩存版本上使用Lazy<T>的唯一原因是,如果你不確定用戶是否真的要加載該屬性。

Lazy<T>的要點是等到用戶需要資源,然后及時在該實例創建它。 如果他們總是需要資源,那么使用Lazy<T>是沒有意義的,除非你需要一些其他目的,比如它是線程安全的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM