[英]Cached Property: Easier way?
我有一個對象的屬性計算起來很昂貴,所以它們只在第一次訪問時計算然后緩存。
private List<Note> notes;
public List<Note> Notes
{
get
{
if (this.notes == null)
{
this.notes = CalcNotes();
}
return this.notes;
}
}
我想知道,有沒有更好的方法來做到這一點? 是否有可能在 C# 中創建緩存屬性或類似的東西?
就語法而言,如果您想花哨,可以使用空合並運算符,但它不一定具有可讀性。
get
{
return notes ?? (notes = CalcNotes());
}
編輯:更新禮貌馬修。 另外,我認為其他答案對提問者更有幫助!
在 .NET 3.5 或更早版本中,您擁有的是一個非常標准的實踐和一個很好的模型。
(雖然,我會建議返回IList<T>
或IEnumerable<T>
如果可能的話,而不是List<T>
的公共API中- List<T>
應該是一個實現細節...)
但是,在 .NET 4 中,這里有一個更簡單的選項: Lazy<T>
。 這讓您可以:
private Lazy<IList<Note>> notes;
public IEnumerable<Note> Notes
{
get
{
return this.notes.Value;
}
}
// In constructor:
this.notes = new Lazy<IList<Note>>(this.CalcNotes);
對我來說看起來很標准。 你在做什么很好。
問題是??
是如果CalcNotes()
返回null
那么它將不再被緩存。 如果例如0
和NaN
都允許作為屬性值,則值類型同上。
更好的是“面向方面”的解決方案,例如Post - Sharp使用屬性然后修改 MSIL(字節碼)。
代碼如下所示:
[Cached]
public List<Note> Notes { get { return CalcNotes(); } }
編輯: CciSharp.LazyProperty.dll正是這樣做的!!!
是的,這是可能的。 問題是,這樣做你贏了多少——你仍然需要在某處初始化代碼,所以你最多只能保存條件表達式。
不久前,我實現了一個類來處理這個問題。 您可以在這個問題中找到發布的代碼,我在那里詢問這是否是一個好主意。 答案中有一些有趣的意見,請務必在決定使用之前閱讀所有內容。
一個Lazy<T> 類與我上面鏈接的實現基本相同,已添加到 .NET 4 框架中; 因此,如果您使用的是 .NET 4,則可以使用它。請參見此處的示例: http : //weblogs.asp.net/gunnarpeipman/archive/2009/05/19/net-framework-4-0-using-system-懶人-lt-t-gt.aspx
如果該值難以計算,我通常更喜歡使用方法 ( GetNotes()
)。 沒有什么可以阻止您使用方法緩存值,此外,如果適用,您可以添加[Pure]
屬性 (.NET 4) 以指示該方法不會改變對象的狀態。
如果您確實決定保留以下內容,我建議:
每當您有一個延遲評估的屬性時,您應該添加以下屬性以確保在調試器中運行的行為與在調試器之外運行的行為相同:
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
此外,從 .NET 4 開始,您可以使用以下內容:
// the actual assignment will go in the constructor.
private readonly Lazy<List<Note>> _notes = new Lazy<List<Note>>(CalcNotes);
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public List<Note> Notes
{
get { return _notes.Value; }
}
問題是陳舊的,但這是你在2019年的表現 - 默認值的自動屬性(C#6.0及更高版本)
public List<Note> Notes { get; private set; } = CalcNotes();
帶有 C# 8 和空合並賦值的兩行選項:
private List<Note>? notes;
public List<Note> Notes => notes ??= CalcNotes();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.