I have a C# record like the following, with a property that is expensive to compute:
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 } };
Run Code Online (Sandbox Code Playgroud)
Instead of re-computing the ExpensiveToComputeProperty value on every access, I would like to compute it only once, after "construction". But apparently with C# records, the constructor is not invoked again after modification with with. I tried the following ways to fix this:
class instead, but that way I can no longer use the with syntax, which I'd like to keep using.ExpensiveToComputeProperty in a regular property or field. This does not work, because it is initialized once, but not after changing SomeDictionary with with.有没有一种方法可以使用记录来避免重新进行昂贵的计算?
您可以使用自定义 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}");
}
}
}
Run Code Online (Sandbox Code Playgroud)