缓存属性:更简单的方法?

Pet*_*rdk 37 c# caching properties

我有一个对象,其属性的计算成本很高,因此它们仅在首次访问时计算,然后进行缓存.

 private List<Note> notes;
 public List<Note> Notes
    {
        get
        {
            if (this.notes == null)
            {
                this.notes = CalcNotes();
            }
            return this.notes;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我想知道,有更好的方法吗?是否有可能在C#中创建一个Cached属性或类似的东西?

xyz*_*xyz 23

就语法而言,如果你想要花哨,你可以使用null-coalescing运算符,但它不一定是可读的.

get
{
    return notes ?? (notes = CalcNotes());
}
Run Code Online (Sandbox Code Playgroud)

编辑:马修更新了礼貌.另外,我认为其他答案对提问者更有帮助!

  • `返回笔记?(notes = CalcNotes());`效率稍高. (4认同)
  • 那么 ??= 运算符又如何呢?`笔记??= CalcNotes()` (4认同)

Ree*_*sey 21

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

  • 看起来很有趣,太糟糕了,你仍然需要一个支持变量.代码的数量在整个课程中更加分散,而且编写的代码并不少,所以我不会说真正的好处.应该有一个Lazy Property构造方式,就像{get; private set;}但随后引用了需要调用的计算方法. (7认同)

Mik*_*ail 6

问题??是,如果CalcNotes()返回,null那么它将不再被缓存.值类型同上举例来说,如果既0NaN被允许作为属性值.

更好的是一个"面向方面"的解决方案,像Post - Sharp使用属性然后修改MSIL(字节码).

代码看起来像:

[Cached]
public List<Note> Notes { get { return CalcNotes(); } }
Run Code Online (Sandbox Code Playgroud)

编辑: CciSharp.LazyProperty.dll正是这样做的!

  • 不要修补编译器发出的真实代码。时期。 (3认同)

Ode*_*ded 5

对我来说看起来很标准。你在做什么很好。


Noa*_*ahl 5

使用 C# 8 和空合并赋值的两行选项:

private List<Note>? notes;
public List<Note> Notes => notes ??= CalcNotes();
Run Code Online (Sandbox Code Playgroud)