如何设计小型的基于getter的类而不需要多次执行
本文关键字:不需要 执行 getter 小型 | 更新日期: 2023-09-27 18:13:23
我喜欢写很多小的getter属性,准确地描述它们的含义。
然而,这会导致重复的、昂贵的计算。
我所知道的所有避免这种情况的方法都会使代码的可读性降低。
伪代码示例:
ctor(decimal grossAmount, taxRateCalculator, itemCategory)
{
// store the ctor args as member variables
}
public decimal GrossAmount { get { return _grossAmount, } }
private decimal TaxRate { get { return _taxRateCalculater.GetTaxRateFor(_itemCategory); } } // expensive calculation
public decimal TaxAmount { get { return GrossAmount * TaxRate; } }
public decimal NetAmount { get { return GrossAmount - TaxAmount; } }
在这个例子中,每个属性的作用非常明显,因为它们是简单的访问器。TaxRate已经被重构到它自己的属性中,所以它的作用也是显而易见的。如果_taxRateCalculator操作非常昂贵,如何避免重复执行而不破坏代码?
在我的实际场景中,我可能有10个需要这样处理的字段,所以10组_backing或Lazy字段会很难看。
缓存值
private decimal? _taxRate = null;
...
private decimal TaxRate
{
get
{
if (!this._taxRate.HasValue) {
this._taxRate = _taxRateCalculator.GetTaxRateFor(_itemCategory);
}
return this._taxRate.Value;
}
}
你可以创建一个方法,每次调用它都会重新计算你的值。
这个解决方案的优点是
- 你可以手动重新计算属性
- 你可以实现某种Eventlistner,它可以在任何事情发生时轻松调用你的重新计算
.
ctor(decimal grossAmount, taxRateCalculator, itemCategory)
{
// store the ctor args as member variables
recalculate();
}
public decimal GrossAmount { get; private set; }
public decimal TaxAmount { get; private set; }
public decimal NetAmount { get; private set; }
public void recalculate();
{
// expensive calculation
var _taxRate = _taxRateCalculater.GetTaxRateFor(_itemCategory);
GrossAmount = grossAmount;
TaxAmount = GrossAmount * _taxRate ;
NetAmount = GrossAmount - _taxRate;
}
Profile。找出应用程序在哪些地方花费了大部分时间,这样就可以找到需要改进的地方。关注最严重的问题,除非对用户体验有重大影响,否则性能优化是没有意义的。
当您确定热点时,您需要做出决策-优化是否值得花费成本?如果是,请继续。使用后备字段来存储昂贵的计算是避免重复昂贵计算的标准方法。只是要确保只在重要的地方应用它,以保持代码的简单。
这真的是一个常见的做法,只要你确保你是一致的(例如,如果一些变化可能会改变税率,你想要无效的存储值,以确保它得到重新计算),你将会很好。只要确保您正在修复一个真正的性能问题,而不是仅仅追求一些性能理想=)
我认为没有办法。您希望缓存数据而不需要缓存。您可以在GetTaxRateFor(…)
方法中构建缓存功能,但我怀疑这是您调用的唯一昂贵的方法。
所以最短的方法是BackingField。我通常是这样做的:
private decimal? _backingField;
public decimal Property { get { return _backingField ?? (_backingField = expensiveMethode()).Value; } }