公式递归引用,最终计算出每个公式的值

using System;
using System.Collections.Generic;
using System.Data;

namespace Compute
{
    public class Formula
    {
        public string Name { get; set; }
        public string Expression { get; set; }
        public decimal? Value { get; set; }
        public List<Formula> Dependencies { get; set; }

        public decimal Calculate()
        {
            if (Value.HasValue) // 如果已经计算过,直接返回
            {
                return Value.Value;
            }
            else
            {
                foreach (Formula dependency in Dependencies)
                {
                    dependency.Calculate(); // 计算依赖项的值
                }
                var expression = Expression;
                foreach (var dependency in Dependencies)
                {
                    expression = expression.Replace(dependency.Name, dependency.Value.ToString());
                }
                if (string.IsNullOrWhiteSpace(expression))
                    return 0;
                else
                    Value = Convert.ToDecimal(new DataTable().Compute(expression, null));
                return Value.Value;
            }
        }
    }
}

public decimal Calculate(HashSet<string> visitedFormulas = null)
{
    if (Value.HasValue)
    {
        return Value.Value;
    }
    else
    {
        visitedFormulas ??= new HashSet<string>();  // 创建一个空的 HashSet

        if (visitedFormulas.Contains(Name))  // 检查是否存在循环引用
        {
            // 处理循环引用的逻辑,例如记录错误日志并返回一个默认值
            Console.WriteLine($"循环引用: {Name}");
            return 0;
        }

        visitedFormulas.Add(Name);  // 将当前公式的名称添加到已访问的集合中

        foreach (Formula dependency in Dependencies)
        {
            dependency.Calculate(visitedFormulas);  // 传递已访问的集合给依赖项的计算方法
        }

        var expression = Expression;
        foreach (var dependency in Dependencies)
        {
            expression = expression.Replace(dependency.Name, dependency.Value.ToString());
        }

        if (string.IsNullOrWhiteSpace(expression))
            return 0;
        else
            Value = Convert.ToDecimal(new DataTable().Compute(expression, null));

        visitedFormulas.Remove(Name);  // 在计算完当前公式后,将其从已访问的集合中移除

        return Value.Value;
    }
}

Formula类表示一个公式,包含公式的名称、表达式、值以及依赖项列表。Calculate方法用于计算公式的值,它会递归计算所有依赖项的值,并在所有依赖项的值都已计算完成后,计算当前公式的值。在计算公式值的过程中,如果某个公式的值已经计算过,则直接返回该值,以避免无限递归。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值