首页 > 解决方案 > C# - 作为对象的计算 - 具有许多依赖关系的许多计算

问题描述

我在 Excel 中开发了一个相当复杂的电子表格,我的任务是将其转换为 C# 程序。

我想弄清楚的是如何在 C# 中表示我的电子表格中的计算。

计算有很多依赖关系,以至于它几乎看起来像是一个网络,而不是一个漂亮的整洁层次结构。

我能想到的设计方案是这样的:

我希望这是有道理的。我正在为此输入代码,但我对 C# 仍然很陌生,所以至少知道我在正确的轨道上是一个福音:) 澄清一下,这是一个设计查询,我只是在寻找更有经验的人用 C# 比我自己,来验证我的方法是否明智。

感谢您对这个问题的任何帮助,我很想听听您的想法!:)

编辑*

我相信循环状态检查需要“完成”状态和“就绪”状态,以防止在尝试评估未评估先例的计算时可能发生的错误。这是必要的吗?

我将其设置为默认设置“任何 CPU”。

编辑*

例如,一个对象是一行“V_dist”,它具有长度,作为一个属性。它的长度“V_dist.calc_formula”是根据其他两个对象“hpc*Tan(dang)”计算得出的

public class inputs
{
    public string input_name;
    public int input_angle;
    public int input_length;
}
public class calculations
{
    public string calc_name; ///calculation name
    public string calc_formula; ///this is just a string containing formula
    public double calculationdoub; ///this is the calculation
    public int completed; ///this will be set to 1 when "calculationdoub" is nonzero
    public int ready; ///this will be set to 1 when dependent object's "completed" property = 1
}
public class Program
{
    public static void Main()
    {
        ///Horizontal Length
        inputs hpc = new inputs();
        hpc.input_name = "Horizontal "P" Length";
        hpc.input_angle = 0;
        hpc.input_length = 200000;

        ///Discharge Angle
        inputs dang = new inputs();
        dang.input_name = "Discharge Angle";
        dang.input_angle = 12;
        dang.input_length = 0;

        ///First calculation object
        calculations V_dist = new calculations();
        V_dist.calc_name = "Vertical distance using discharge angle";
        V_dist.calc_formula = "hpc*Tan(dang)";
        **V_dist.calculationdoub = inputs.hpc.length * Math.Tan(inputs.dang.input_angle);**
        V_dist.completed = 0;
        V_dist.ready = 0;
    }
}

需要注意的是,我还没有添加其他功能,例如循环,以及控制两个布尔属性的逻辑

标签: c#excelpseudocode

解决方案


你有一些好主意,但如果我理解你想要做什么,我认为有一个更惯用的 - 更多的 OOP 方法来解决这个问题,而且也不那么复杂。我假设您有一个标准电子表格,其中电子表格上有许多行都有效地具有相同的列。也可能是您在电子表格的不同部分有不同的列。

我已经将几个电子表格转换为应用程序,并且我已经确定了这种方法。我想你会喜欢的。

对于每组标题,我会将其建模为单个对象类。每一列都是类的一个属性,每一行都是一个对象实例。

在几乎非常罕见的情况下,我会说简单地对您的属性进行建模以包含计算。一个简单的盒子示例如下:

public class Box
{
    public double Length { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }

    public double Area
    {
        get { return 2*Height*Width + 2*Length*Height + 2*Length*Width; }
    }

    public double Volume
    {
        get { return Length * Width * Height; }
    }
}

这里的想法是,如果有使用其他计算属性/列作为输入的属性(Excel 中的列),只需使用属性本身:

public bool IsHuge
{
    get { return Volume > 50; }
}

.NET 将为您处理所有繁重的工作和依赖项。

在大多数情况下,与 Excel 相比,这将在 C# 中运行,而且我认为您不必担心设置级联对象的方式的计算速度。

当我说除极少数情况外的所有情况时,如果您的属性在计算上非常昂贵,那么您可以将这些属性设为私有,然后触发计算。

public class Box
{
    public double Length { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }

    public double Area { get; private set; }
    public double Volume { get; private set; }
    public bool IsHuge { get; private set; }

    public void Calculate()
    {
        Area = 2*Height*Width + 2*Length*Height + 2*Length*Width;
        Volume = Length * Width * Height;
        IsHuge = Volume > 50;
    }
}

在你走这条路之前,我建议你做性能测试。除非您有数百万行和/或非常复杂的计算,否则我怀疑第二种方法是否值得,并且您的好处是不需要定义何时计算。当且仅当访问该属性时,才会发生这种情况。


推荐阅读