在 C# 记录中缓存昂贵的重新计算属性或字段
Caching expensive-to-recompute properties or fields in C# records
我有一个如下所示的 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
存储在常规 属性 或字段中。这不起作用,因为它被初始化了一次,但在将 SomeDictionary
更改为 with
之后就没有了。
- AFAIK,计划引入良好的语法,让我在 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}");
}
}
}
我有一个如下所示的 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
存储在常规 属性 或字段中。这不起作用,因为它被初始化了一次,但在将SomeDictionary
更改为with
之后就没有了。 - AFAIK,计划引入良好的语法,让我在 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}");
}
}
}