缓存c#记录中重计算代价高的属性或字段



我有一个像下面这样的c#记录,它有一个计算成本很高的属性:

sealed record MyAwesomeRecord(Dictionary<int, int> SomeDictionary)
{
public int ExpensiveToComputeProperty => SomeDictionary.Sum(e => e.Value);
//...
}
var original = new MyAwesomeRecord( new() { [0] = 0 });
var modified = original with { SomeDictionary = new() { [1] = 1 } };

我不希望每次访问都重新计算ExpensiveToComputeProperty值,而是希望在"构造"之后只计算一次。但显然,对于c#记录,使用with修改后不会再次调用构造函数。我尝试了以下方法来解决这个问题:

  • 使用常规的class代替,但这样我就不能再使用with语法,我想继续使用。
  • ExpensiveToComputeProperty存储在常规属性或字段中。这不起作用,因为它只初始化一次,而不是在用with更改SomeDictionary之后。
  • 我敢说,c# 10计划引入好的语法,让我在c# 10中保持这个属性的更新。遗憾的是,c# 10还没有出现。

是否有一种方法来使用记录,避免重新做昂贵的计算?

您可以使用自定义setter来代替该属性的默认setter。在这个setter中,您可以进行昂贵的计算。

下面是一个完整的例子(测试和工作):

using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
sealed record MyAwesomeRecord
{
public MyAwesomeRecord(Dictionary<int, int> SomeDictionary)
{
this.SomeDictionary = SomeDictionary;
}
public int ExpensiveToComputeProperty { get; private set; }
private Dictionary<int, int>? _SomeDictionary;
public Dictionary<int, int> SomeDictionary
{
get => _SomeDictionary!;
set
{
_SomeDictionary = value;
ExpensiveToComputeProperty = SomeDictionary.Sum(e => e.Value);
}
}
//...
}
class Program
{
static void Main()
{
var original = new MyAwesomeRecord(new() { [0] = 0 });
Console.WriteLine($"ExpensiveToComputeProperty = {original.ExpensiveToComputeProperty}");
var modified = original with { SomeDictionary = new() { [1] = 1 } };
Console.WriteLine($"ExpensiveToComputeProperty = {modified.ExpensiveToComputeProperty}");
}
}
}

最新更新