c# 这个设计是“正确的”吗?

Posted

技术标签:

【中文标题】c# 这个设计是“正确的”吗?【英文标题】:c# is this design "Correct"? 【发布时间】:2011-04-25 22:48:18 【问题描述】:

我目前有以下

        if (!RunCommand(LogonAsAServiceCommand))
            return;

        if (!ServicesRunningOrStart())
            return;

        if (!ServicesStoppedOrHalt())
            return;

        if (!BashCommand(CreateRuntimeBashCommand))
            return;

        if (!ServicesStoppedOrHalt())
            return;

        if (!BashCommand(BootstrapDataBashCommand))
            return;

        if (!ServicesRunningOrStart())
            return;

这样做会更干净吗?安全吗?

        if (
           (RunCommand(LogonAsAServiceCommand))
        && (ServicesRunningOrStart())
        && (ServicesStoppedOrHalt())
        && (BashCommand(CreateRuntimeBashCommand))
        && (ServicesStoppedOrHalt())
        && (BashCommand(BootstrapDataBashCommand))
        && (ServicesRunningOrStart())
        )
        
               // code after "return statements" here
        

【问题讨论】:

除了第一个更容易调试(和设置断点)之外,完全一样,只是风格问题。 我同意@Kirk Woll,如果编译器/抖动足够聪明,优化后它们应该是一样的。 【参考方案1】:

当我看到第一种方法时,我的第一个想法是代码以这种方式编写的原因是所涉及的操作可能具有副作用。从方法的名称来看,我认为它们可以吗?如果是这样,我肯定会采用第一种方法而不是第二种方法;我认为您的代码的读者会发现看到短路的&& 表达式被用于有条件地执行副作用时会感到非常困惑。

如果没有副作用,两者都可以;它们都是完全可读的。如果您发现还有多个条件或条件本身在不同的场景中有所不同,您可以尝试以下方法:

Func<bool>[] conditions = ...
if(conditions.Any(condn => condn()))

   ...

但是,在您的情况下,我不会真正采用这种方法。

【讨论】:

“副作用”是什么意思? en.wikipedia.org/wiki/Side_effect_(computer_science)。实际上,在这种情况下,我的意思是选择短路还是不短路会在程序状态中引入可观察到的功能差异。 +1 提供一个好的规则来决定哪个语句更易读。 Eric Lippert 在 SO 上发表了一篇文章,在三元运算符的上下文中讨论此规则,但我似乎找不到它。 Eric Lippert 的讨论,实际上只是外围相关:***.com/questions/3909849/…【参考方案2】:

第一个代码是一组 OR 语句吗?

if ( 
       (!RunCommand(LogonAsAServiceCommand)) 
    || (!ServicesRunningOrStart()) 
    || (!ServicesStoppedOrHalt()) 
    || (!BashCommand(CreateRuntimeBashCommand)) 
    || (!ServicesStoppedOrHalt()) 
    || (!BashCommand(BootstrapDataBashCommand)) 
    || (!ServicesRunningOrStart()) 

【讨论】:

如果您将其作为 OR 语句执行,您将获得在任何条件为真时立即返回的效率,而不是等待查看它们是否都为真。 &amp;&amp;|| 都是短路的,所以这样做并没有真正的优势。 +1 用于性能和纠正 OP 的第二个解决方案。 @BrunoLM:这与 OP 的第二个解决方案相同。唯一的区别是 if 和 else 块的内容是相反的(想想德摩根定律)。 @BrunoLM - 是一样的。 OP 使用&amp;&amp;,但不反转输出。 Mark 只是简单地使用|| 翻转了这一点,并反转了每个函数的输出。请参阅上面 Brian 的评论。【参考方案3】:

两者都可以。但是从风格的角度来看,我建议由于这是一系列命令,您可以使用 List&lt;Action&gt; 来保存这些命令并使函数数据驱动。

(new Action[]   func1, func2, .... ).ToList().ForEach(a => a());

当然,因为函数有不同的签名,你可能需要做多个......

这又是一个风格问题....

【讨论】:

这是一个不错的方法,但仍然不是很适合调试。尤其是当您在整个列表中填充 lambda 时。不过普通方法应该没问题。 同意调试注释。我的代码非常受数据驱动,但它使它对单元测试更加友好。此外,这些天我更倾向于使用日志记录而不是调试来进行分析 这种东西在 vs2010 中调试得更好:)【参考方案4】:

你应该坚持任何更易读、更容易理解的东西。

除非它真的是低效的。

【讨论】:

【参考方案5】:

如果您多次使用此代码,我建议您将其放在单独的方法中,例如:

public static class HelperClass

  public static bool ServicesRunning()
  
    // Your code here... 
  

并在需要时调用它

public class SomeClass

  // Constructors etc...
  public void SomeMethod()
  
     if(HelperClass.ServicesRunning())
     
        // Your code here...
     
  

【讨论】:

嗯,不是很清楚这是您的设计。但如果这就是你已经在做的事情,我只能说我同意那个设计。使用长 && / || if 语句很容易变得混乱(在我看来)。

以上是关于c# 这个设计是“正确的”吗?的主要内容,如果未能解决你的问题,请参考以下文章

Connectionstring:它是正确的形式吗?

c# .net - 时间戳问题

从共享 ArrayPool 中租用和返回 C# 中的多维数组的正确方法?

什么时候在 C# 中返回空引用类型是正确的 [重复]

C#如何检查if语句的哪一部分是正确的[关闭]

C# 如何正确的获取当前登录用户 id