I have a object with properties that are expensive to compute, so they are only calculated on first access and then cached.
private List<Note> notes;
public List<Note> Notes
{
get
{
if (this.notes == null)
{
this.notes = CalcNotes();
}
return this.notes;
}
}
I wonder, is there a better way to do this? Is it somehow possible to create a Cached Property or something like that in C#?
As far as syntax goes, you can use the null-coalescing operator if you want to be fancy, but it's not necessarily as readable.
Edit: Updated courtesy of Matthew. Also, I think the other answers are more helpful to the question asker!
The problem with
??
is that ifCalcNotes()
returnsnull
then it will not be cached any more. Ditto for value types if for example both0
andNaN
are allowed as property value.Much better would be an "aspect-oriented" solution, something like Post-Sharp does using attributes and then modifying MSIL (bytecode).
The code would look like:
EDIT: CciSharp.LazyProperty.dll does exactly this!!!
If the value is non-trivial to compute, I generally prefer using a method (
GetNotes()
). There's nothing stopping you from caching the value with a method, plus you can add the[Pure]
attribute (.NET 4) if applicable to indicate the method does not alter the state of the object.If you do decide to stay with the following, I recommend:
Whenever you have a lazily-evaluated property, you should add the following attribute to ensure that running in the debugger behaves the same as running outside of it:
Also, starting with .NET 4, you can use the following:
In .NET 3.5 or earlier, what you have is a very standard practice, and a fine model.
(Although, I would suggest returning
IList<T>
, orIEnumerable<T>
if possible, instead ofList<T>
in your public API -List<T>
should be an implementation detail...)In .NET 4, however, there is a simpler option here:
Lazy<T>
. This lets you do:Looks pretty standard to me. What you are doing is fine.
The question is old, but here's how you do it in 2019 - auto properties with default values (C# 6.0 and higher)