首页 > 解决方案 > 在 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. 我尝试了以下方法来解决这个问题:

有没有办法使用记录来避免重新进行昂贵的计算?

标签: c#recordc#-9.0

解决方案


您可以使用自定义设置器,而不是使用属性的默认设置器。在这个设置器中,您可以进行昂贵的计算。

这是一个完整的示例(经过测试和工作):

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}");
        }
    }
}

推荐阅读