我已经在Excel中开发了一个相当复杂的电子表格,我的任务是将其转换为C#程序。
我想弄清楚的是如何用C#表示电子表格中的计算。
这些计算具有许多依赖性,以至于它几乎看起来像是一个网络,而不是一个整洁的层次结构。
我能想到的设计解决方案是:
每个对象都有一个整数或双精度值,其中包含计算。此计算具有来自其他对象的输入,因此需要先对其进行评估,然后才能执行。
每个对象都有第二个整数“ completed”,如果先前的计算成功,则结果为1
我希望这是有道理的。我正在为此输入代码,但我仍然对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;
}
}
应该注意,我还没有添加的其他功能,例如循环和控制两个布尔属性的逻辑
您有一些好主意,但是如果我了解您要尝试做的事情,我认为还有一种更惯用的-更多的面向对象的方法来解决这个问题,而且也要简单得多。我假设您有一个标准电子表格,该电子表格上有很多行,而所有行实际上都具有相同的列。也可能是您在电子表格的不同部分具有不同的列。
我已经将多个电子表格转换为应用程序,并且我决定采用这种方法。我想你会喜欢的。
对于每组标题,我会将其建模为单个对象类。每列将是该类的一个属性,而每一行将是一个对象实例。
在极少数情况下,我会说,只需对您的属性进行建模以包括计算即可。一个盒子的简单例子就是这样:
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;
}
}
在走这条路之前,建议您进行性能测试。除非您有数百万的行和/或非常复杂的计算,否则我怀疑第二种方法是否值得,并且您的好处是不必定义何时计算。它仅在访问该属性时发生。