C# 三方计算
我有一个包含三个字段的数据对象,a、B和C。问题是用户可以设置其中任何一个字段,因为: A*B=C 因此,如果用户从设置a和B开始,将计算C。但是,如果用户设置了C,a,则会重新计算,因此会根据用户设置的最后一个字段进行隐式锚定 我希望避免一个包含大量标志成员变量的解决方案。关于如何编写这个类的代码而不需要下面这样的东西,有什么最佳实践吗C# 三方计算,c#,C#,我有一个包含三个字段的数据对象,a、B和C。问题是用户可以设置其中任何一个字段,因为: A*B=C 因此,如果用户从设置a和B开始,将计算C。但是,如果用户设置了C,a,则会重新计算,因此会根据用户设置的最后一个字段进行隐式锚定 我希望避免一个包含大量标志成员变量的解决方案。关于如何编写这个类的代码而不需要下面这样的东西,有什么最佳实践吗 public class Object { private double _A; private double _B; priv
public class Object
{
private double _A;
private double _B;
private double _C;
private bool _enteredA;
private bool _enteredB;
private bool _enteredC;
public double A
{
get
{
if (_enteredC)
{
return _C / _B;
}
else
{
return _A;
}
}
}
设置A、B和C的逻辑是否应始终处于“get”或“set”状态
有什么更干净的方法可以做到这一点吗?所以你的规则是:
A = C / B
B = C / A
C = A * B
您需要做的是记住用户输入的最后两个字段,并从中计算第三个字段。因此,如果他们先输入A,然后输入B,则计算C。如果他们随后更改C,则重新计算A,依此类推
如果您想在不使用布尔标志的情况下对其进行编码,有几种不同的方法可以做到这一点。队列或只是一个简单的数组/映射即可:
editOrder = {A : 0, B : 0, C : 0 } // (or just use 0, 1, 2)
editCount = 0;
every time any field is edited :
editCount = editCount + 1
editOrder[field] = editCount
if two fields have an editOrder > 0
recalculate the field with the lowest editOrder
用法示例:
Field changed editOrder recalculate field
A 1,0,0 -
A 2,0,0 -
B 2,3,0 C
C 2,3,4 A
C 2,3,5 A
B 2,6,5 A
A 7,6,5 C
创建一个私有方法来执行以下计算
private void calculateFields(){
if (_b != INIT_VALUE && _c != INIT_VALUE)
_a = _c / _b;
if (_a != INIT_VALUE && _c != INIT_VALUE)
_b = _c / _a;
if (_a != INIT_VALUE && _b != INIT_VALUE)
_c = _a * _b;
}
public double A
{
get{
return _a;
}
set{
_a = value;
calculateFields();
}
}
对财产B和C也要这样做。简单的回答是否定的
您可以创建一个适配器来处理所描述的逻辑。您将把复杂性从这个类转移到另一个类。您是否在寻找类似的东西(感谢您费心解决每个值的等式):
您声明您的属性具有关系“A*B=C”。所以,你们的课堂应该表达这一点。A和B是自变量,所以它们有简单的setter和getter,它们只获取和设置一个字段。C是一个依赖变量,因此它应该只有一个getter,并根据a和B执行计算:
class Foo
{
private double m_a;
public double A
{
get { return m_a; }
set { m_a = value; }
}
private double m_b;
public double B
{
get { return m_b; }
set { m_b = value; }
}
public double C
{
get { return A * B; }
}
}
可以编写一个编辑器,允许对A和B进行简单的编辑。如果(并且仅当)用户已经编辑了A或B,它还允许用户编辑C。视图将存储一些状态,以指示上次编辑的字段(如果有),因此在编辑概念C时,可以对A或B应用适当的更改
现在,如果视图不知道C的计算,可以将方法添加到Foo类中的“SetAGivenC()”和“SetBGivenC()”:
现在,当编辑“C”时,GUI只调用其中一个方法
我不明白“用户设置的最后一个字段”是什么意思。假设屏幕上有两个编辑器(都绑定到同一个Foo实例),用户在第一个编辑器中编辑A,然后在第二个编辑器中编辑B,然后在第一个编辑器中编辑C。设置C时,会调整什么?A还是B?如果你能回答这个问题,你就会知道哪个类应该跟踪“用户设置的最后一个字段”——应该是模型还是视图?我希望在这种情况下会调整A,并且视图会跟踪最后编辑的字段。但这是另一天的问题
编辑:
天哪,我甚至把自己的病态病例都塞满了
我将再次尝试最后一段:
我不明白“用户设置的最后一个字段”是什么意思。假设屏幕上有两个编辑器(都绑定到同一个Foo实例),用户在第一个编辑器中编辑A然后编辑B,用户在第二个编辑器中编辑B然后编辑A,用户在第一个编辑器中编辑C。设置C时,会调整什么?A还是B?如果你能回答这个问题,你就会知道哪个类应该跟踪“用户设置的最后一个字段”——应该是模型还是视图?我希望在这种情况下会调整A,并且视图会跟踪最后编辑的字段。但这是另一天的问题 乔纳森
关于你计算方法中的错误,我的观点如下:
在您编写的代码中,发生了以下事件序列
given a valid state at some point of time.
[a = 1, b = 3, c = 3]
用b=4调用setter,然后通过代码计算a和c:
1. first sets b b = 4
2. first calculates a a = c / b = 3 / 4 = 3/4
3. then calculates c c = a * b = 3/4 * 4 = 3
最后一个元组是
[a = 3/4, b = 4, c = 3]
本质上,对于您的类(如当前编写的)
计算(3)是无用的,因为如果A
已经从C
和B
派生,则从A
和B
重新派生C
永远不会改变C
的值
设置
A
或B
应计算C
,并且有一种特殊情况,即设置C
计算A
或B
,而不使用布尔值来知道是哪一种。(贴出的问题)你能再解释一下吗?如果我说C=4.3/1.9?你的逻辑是什么?这样做的目的是什么?我不明白你的问题。我添加了一些成员变量以使其更清晰。当对象实例化时,所有成员都设置为0,则A*B=C最初有效。假设您不关心跟踪用户设置的字段与仍具有初始值的字段之间的关系,是否公平?@Ates,@ak声明“将计算A&B和C。但如果用户设置了C,a将被重新计算”。这与您的假设相矛盾。解决方案需要跟踪设置的顺序。@ak声明“a&B,C将被计算。”。但如果用户设置了C,则会重新计算a”“为什么不呢?你能告诉我们这个用例吗?可能有一种更简单的方法来处理这个问题,而不是将所有三个变量集中在一个对象中。这是正确的。但是我想用最好的方法来编写这个代码,而不让所有这些布尔标记挂在周围。你需要这些标记,因为你需要跟踪哪些字段是按什么顺序设置的。不要认为这是可行的,因为我很确定他想让它无限期地运行计算。根据“将计算设置A和B、C。但是,如果用户设置了C,a重新计算“这是不正确的。如果设置了a,则不能从a,C中计算B,然后从B,a中计算C。类需要接收任意两个变量并计算缺少的一个。Calc
1. first sets b b = 4
2. first calculates a a = c / b = 3 / 4 = 3/4
3. then calculates c c = a * b = 3/4 * 4 = 3
[a = 3/4, b = 4, c = 3]
setting b alters a -> leaves c unaffected.
setting c alters a -> leaves b unaffected.
setting a alters b -> leaves c unaffected