具有缓存结果的属性或get方法

时间:2019-01-18 11:05:54

标签: c# algorithm design-patterns

我有一种方法需要200毫秒才能运行,因此希望将结果缓存。此结果将被频繁使用,但永远不会改变。

我不确定是否最好的解决方案是什么,我应该将其放在属性或get方法上吗?

例如:

1

private string _result;
public string Result => _result ?? (_result = GetSlowResult());

2

private string _result;
public string GetResult() => _result ?? (_result = GetSlowResult());

就个人而言,我通常希望它从“现在”而不是“以后”可用,但是使用Get方法,我希望结果总是检索新鲜的GetSlowResult而不是使用缓存的值。我可以将方法名称更改为GetCachedResult,但是我也没有因此而出售,因为那样看来您首先需要调用GetResult方法。

对此有任何指导原则吗?你喜欢什么?

2 个答案:

答案 0 :(得分:1)

我建议您使用Lazy<T>类。它使您通过一个讨论如何创建该对象的工厂,此后,仅在您第一次请求该对象时才创建该对象,然后使用相同的引用(缓存的值)。

这是它的外观:

Lazy<T> Result = new Lazy<T>(GetSlowResult); //T is your type

然后,要使用结果,只需获取她的财产Value

T myResult = Result.Value;

您可以在official dotnet docs中查看有关此内容的更多信息。

答案 1 :(得分:0)

我将使用只读属性和填充该属性的方法来完成此操作。

如果您知道需要此结果,则可以在开始时将其加载-在启动服务,激活ov视图等过程中。

我在WPF应用程序中大多使用ReactiveUI,因此看起来像这样:

// ViewModel constructor
GetResult = ReactiveCommand.CreateFromTask(async () => _model.GetResultAsync()); // notice that method is async
// there is also overload with CancelationToken

_result = GetResult.Retry(3).ToProperty(this, x => x.Result); // we can retry few times and we get change notification

GetResult.Subscribe(result =>{
 // do something as soon as the result is loaded
});   

GetResult.ThrownExceptions.Subscribe( errorHandler);

// ViewModel properties
private ObservableAsProperetyHelper<ResultType> _result;

public ResultType Result => _result.Value;

// view constructor

this.WhenActivated(d =>{ // d is CompositeDisposable for cleanup
  ViewModel.GetResult.Execute().Subscribe().DisposeWith(d); // cancel command if the view is deactivated before it's finished
});

这样,您可以在适当的时候进行异步调用,并将结果存储以备后用。您还可以轻松刷新结果-单独使用惰性属性时,结果会变得很脏。

另一方面,您可以轻松创建加载微调器:

_isBusy = GetResult.IsExecuting.ToProperty(this, x => x.IsBusy);

我在始终在后台运行自定义HTTP服务器的Windows服务中遵循此模式。如果要在特定时刻强制加载,可以await GetResult.Execute()

在我的实践中,这种模式显示的缺点很少-主要是样板代码,但是使用适当的工具,它可以非常快地编写。

如果您正在创建某种服务类型的应用程序,控制台或其他内容,则MVVM模式仍然非常有用,您只是不执行视图。