C# - 计算作为对象 - 具有许多依赖关系的许多计算
C# - Calculations as objects - Many Calculations with Many Dependencies
我在 Excel 中开发了一个相当复杂的电子表格,我的任务是将其转换为 C# 程序。
我想弄清楚的是如何用 C# 表示电子表格中的计算。
计算有很多依赖性,以至于它几乎看起来像一个网络,而不是一个漂亮整洁的层次结构。
我能想到的设计方案是这样的:
- 创建一个对象来表示每个计算。
每个对象都有一个整数或双精度数,其中包含计算。
此计算具有来自其他对象的输入,因此需要在执行之前先对其进行评估。
每个对象都有第二个整数"completed",如果前面的计算成功则计算结果为1
- 每个对象都有第三个整数"ready"
此项要求所有先例对象的 "completed" 整数计算为
“1”,如果不是,则循环跳过此对象
- 循环遍历所有对象,直到所有 "completed" 整数 = 1
我希望这是有道理的。我正在为此输入代码,但我对 C# 还是很陌生,所以至少知道我在正确的轨道上是一个福音 :)
澄清一下,这是一个设计查询,我只是想找比我更有 C# 经验的人来验证我的方法是否合理。
感谢您对此问题的任何帮助,我很想听听您的想法! :)
编辑*
我认为循环状态检查需要 "completed" 状态和 "ready" 状态,以防止尝试评估未评估先例的计算时可能发生的错误。有这个必要吗?
我已将其设置为 "Any 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;
}
}
需要注意的是,我还没有添加其他功能,例如循环,以及控制两个布尔属性的逻辑
你有一些好主意,但如果我理解你正在尝试做什么,我认为有一种更惯用的 - 更多 OOP 的方法来解决这个问题,而且也不那么复杂。我假设您有一个标准电子表格,电子表格上有很多行实际上都具有相同的列。也可能是您在电子表格的不同部分中有不同的列。
我已经将几个电子表格转换为应用程序,并且我已经确定了这种方法。我想你会喜欢的。
对于每组 headers,我会将其建模为单个 object class。每列都是 class 的 属性,每一行都是一个 object 实例。
在极少数情况下,我会说简单地为您的属性建模以包括计算。一个盒子的简单例子是这样的:
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; }
}
}
这里的想法是,如果有使用其他计算的 properties/columns 作为输入的属性(Excel 中的列),只需使用 属性 本身:
public bool IsHuge
{
get { return Volume > 50; }
}
.NET 将为您处理所有繁重的工作和依赖项。
在大多数情况下,与 Excel 相比,这将在 C# 中运行,而且我认为您不必担心设置级联的方式的计算速度 objects.
当我说除极少数情况外的所有情况时,如果您的属性在计算上非常昂贵,那么您可以将这些属性设为私有,然后触发计算。
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;
}
}
在您走这条路之前,我建议您进行性能测试。除非你有数百万行 and/or 非常复杂的计算,否则我怀疑第二种方法是否值得,而且你的好处是不需要定义何时计算。当且仅当 属性 被访问时才会发生。
我在 Excel 中开发了一个相当复杂的电子表格,我的任务是将其转换为 C# 程序。
我想弄清楚的是如何用 C# 表示电子表格中的计算。
计算有很多依赖性,以至于它几乎看起来像一个网络,而不是一个漂亮整洁的层次结构。
我能想到的设计方案是这样的:
- 创建一个对象来表示每个计算。
每个对象都有一个整数或双精度数,其中包含计算。 此计算具有来自其他对象的输入,因此需要在执行之前先对其进行评估。
每个对象都有第二个整数"completed",如果前面的计算成功则计算结果为1
- 每个对象都有第三个整数"ready" 此项要求所有先例对象的 "completed" 整数计算为 “1”,如果不是,则循环跳过此对象
- 循环遍历所有对象,直到所有 "completed" 整数 = 1
我希望这是有道理的。我正在为此输入代码,但我对 C# 还是很陌生,所以至少知道我在正确的轨道上是一个福音 :) 澄清一下,这是一个设计查询,我只是想找比我更有 C# 经验的人来验证我的方法是否合理。
感谢您对此问题的任何帮助,我很想听听您的想法! :)
编辑*
我认为循环状态检查需要 "completed" 状态和 "ready" 状态,以防止尝试评估未评估先例的计算时可能发生的错误。有这个必要吗?
我已将其设置为 "Any 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;
}
}
需要注意的是,我还没有添加其他功能,例如循环,以及控制两个布尔属性的逻辑
你有一些好主意,但如果我理解你正在尝试做什么,我认为有一种更惯用的 - 更多 OOP 的方法来解决这个问题,而且也不那么复杂。我假设您有一个标准电子表格,电子表格上有很多行实际上都具有相同的列。也可能是您在电子表格的不同部分中有不同的列。
我已经将几个电子表格转换为应用程序,并且我已经确定了这种方法。我想你会喜欢的。
对于每组 headers,我会将其建模为单个 object class。每列都是 class 的 属性,每一行都是一个 object 实例。
在极少数情况下,我会说简单地为您的属性建模以包括计算。一个盒子的简单例子是这样的:
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; }
}
}
这里的想法是,如果有使用其他计算的 properties/columns 作为输入的属性(Excel 中的列),只需使用 属性 本身:
public bool IsHuge
{
get { return Volume > 50; }
}
.NET 将为您处理所有繁重的工作和依赖项。
在大多数情况下,与 Excel 相比,这将在 C# 中运行,而且我认为您不必担心设置级联的方式的计算速度 objects.
当我说除极少数情况外的所有情况时,如果您的属性在计算上非常昂贵,那么您可以将这些属性设为私有,然后触发计算。
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;
}
}
在您走这条路之前,我建议您进行性能测试。除非你有数百万行 and/or 非常复杂的计算,否则我怀疑第二种方法是否值得,而且你的好处是不需要定义何时计算。当且仅当 属性 被访问时才会发生。