Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现布尔逻辑的更干净的方法是在两种情况发生时传递吗?_C#_Optimization_Logic - Fatal编程技术网

C# 实现布尔逻辑的更干净的方法是在两种情况发生时传递吗?

C# 实现布尔逻辑的更干净的方法是在两种情况发生时传递吗?,c#,optimization,logic,C#,Optimization,Logic,这种情况偶尔会发生在我身上,我总是以同样的方式解决它,然后希望有一种更干净的方式 我首先调用相关的实用程序函数,然后是和update调用 SynchA(); SynchB(); UpdateLastTime(); 然后,我添加复选框,以便: if(synchA.Checked) { SynchA(); } if(synchB.Checked) { SynchB(); } 但是现在我只想调用其中一个或两个执行的UpdateLassTime(),因此我最终总是得到: bool synch

这种情况偶尔会发生在我身上,我总是以同样的方式解决它,然后希望有一种更干净的方式

我首先调用相关的实用程序函数,然后是和update调用

SynchA();
SynchB();
UpdateLastTime();
然后,我添加复选框,以便:

if(synchA.Checked)
{
  SynchA();
}
if(synchB.Checked)
{
  SynchB();
}
但是现在我只想调用其中一个或两个执行的UpdateLassTime(),因此我最终总是得到:

bool synchHappened = false;
if(synchA.Checked)
{
  SynchA();
  synchHappened = true;
}
if(synchB.Checked)
{
  SynchB();
  synchHappened = true;
}
if(synchHappened)
{
  UpdateLastTime();
}
最后一步总是困扰着我,因为我把这一点推广到了逻辑的三个分支


对于上述逻辑/场景,我是否可以使用一些明显更好的方法?

主要目标是-每次逻辑发生变化时,代码至少应该受到影响。 因此,你必须构建这样的东西一次,然后它将为你工作

在你的特殊情况下,我建议(不,等等),所以 提取开关逻辑并将其封装到属性中。所以每次当需求发生变化时,您必须更新特定开关的逻辑或主逻辑本身

具有封装规则的交换机:

bool IsUpdateLastTime
{
 get
 {
    // logic here even can be fully or partially injected 
    // as Func<bool>
    return this.IsSyncA || this.IsSyncB;
 }
}

bool IsSyncA { get { return synchA.Checked; } }
bool IsSyncB { get { return synchB.Checked; } }
if (this.IsUpdateLastTime)
{
  this.UpdateLastTime();
}

这类问题才是真正有用的,因为您可以将多个事件合并为一个事件。可以用这样的方法来做

(本例假设使用winforms,但与WPF等类似,只需更改FromEvent的事件名称/泛型类型arg即可。)

var synchAchecked=Observable.FromEvent(synchA.CheckedChanged);
var synchBchecked=Observable.FromEvent(synchB.CheckedChanged);
var merged=可观察的合并(SynchChecked,SynchChecked);
订阅(x=>SynchA());
订阅(x=>SynchB());
Subscribe(x=>UpdateLastTime());

> > P>可以认为这种模式更紧凑(并且可能是可读的),尽管它仍然需要单独的变量。

bool syncHappened = false;
if(syncHappened |= synchA.Checked) SynchA();
if(syncHappened |= synchB.Checked) SynchB();
if(syncHappened) UpdateLastTime();

有些人可能不喜欢这个,但我觉得它非常有用和干净。这有点奇怪,所以使用它的决定权在你

UpdateLastTime(Either(SynchA(synchA.Checked), SynchB(synchB.Checked)));

private bool Either(bool first, bool second)
{
    return first || second;
}
这要求修改
SynchA()
SynchB()
UpdateLastTime()
,使其在shouldRun为false时不工作,并根据是否发生同步返回true或false。

以位C为中心,但:

if (checked_syncs & SYNC_A)
    SyncA();
if (checked_syncs & SYNC_B)
    SyncB();
if (checked_syncs)
    UpdateLastTime();
这样做的好处是,最后一次检查不必更改(除非位用完,在这种情况下,可以切换到更大的基元类型,或者只使用多个基元类型)。它还有一个优点,就是可以有效地并行执行UpdateLassTime()的所有操作,因此它也是一个快速的解决方案


注意:当然,SYNC_A和SYNC_B必须是两个唯一的幂,是的-这可能会破坏您的封装,并假设您可以|=检查发生时的条件(可能不可能,或者如果您谈论的是特定的GUI工具包,则设置一个布尔值是有益的)。

如果使用
if(synchA.Checked | | synchB.Checked)
对于你的最后一个条件?我觉得这看起来相当干净。@adrianbanks,很好的一点-这是我的过度优化,我不想调用属性访问器两次,但这不会伤害到我。@adrianbanks+1对你来说,这就是我要做的。我不认为这样做会保持原来的工作流吗?我拼错了上一个
syncOccess
--它现在已经修复,并编译了.Ick。我避免了比较表达式中的副作用(读流的“while成语”大概是我唯一忽略的一个)。但是,+1是因为“它确实有效”,即使我不推荐它。这是一个有趣的问题,我从来没有想到过。我认为这是行不通的。A被选中,B不是。除非我遗漏了什么(我从不在比较中使用这样的赋值,所以我可能是错的)synchhapped |=SynchB.checked是真的,因此SynchB()运行,即使它不应该运行。这怎么会更好呢?它似乎只是从外部移动了本地逻辑…+1用于不同的方法(而且因为我正在运行:-/)@silev-我认为这段代码与原始代码不同。特别是,您实际上没有调用SynchA或SynchB,| |运算符会短路,如果您要添加它,|运算符可能不会同时调用这两个Synch。@Mystere Man:当然,这是一个如何封装逻辑的示例,因此每次都不会更改主方法流作为每个特定案例的逻辑changes@pst:“刚从外部移动了逻辑”…这足以将许多事情解耦,这样简单的技巧使代码库更干净,更易于维护我认为它正在做我想要的事情-如果我接受这一点造成混乱,我道歉-也就是说,我没有添加一个本地布尔值,而是切换到在表单实例级别封装布尔逻辑…这吸引了我,因为有更少的附加值比我发布的代码更复杂(特别是在我的实际代码大约100行的上下文中)
if (checked_syncs & SYNC_A)
    SyncA();
if (checked_syncs & SYNC_B)
    SyncB();
if (checked_syncs)
    UpdateLastTime();