【问题标题】:Calling methods inside if() - C#在 if() 中调用方法 - C#
【发布时间】:2010-10-09 10:11:43
【问题描述】:

我有几个方法根据它们的成功返回一个布尔值,在 IF() 中调用这些方法有什么问题吗?

//&& makes sure that Method2() will only get called if Method1() returned true, use & to call both methods
if(Method1() && Method2())
{
    // do stuff if both methods returned TRUE
}

如果 Method1() 返回 FALSE,则 Method2() 不需要触发。

让我知道上面的代码有任何问题。

谢谢。

编辑:由于代码没有任何问题,我会接受最有用的答案...添加评论以解决“新手&&&”问题

【问题讨论】:

    标签: c# language-features short-circuiting


    【解决方案1】:

    我会说你可以使用& operator(而不是&&)来保证即使左侧是false,如果将来出于某种原因也会调用这两种方法您希望避免短路。

    逆向适用于 | operator,即使左侧条件的计算结果为 true,右侧条件也会被计算。

    【讨论】:

    • 这就是 & 和 && 的用途。它还从许多 if 中节省了一个(if (foo() && bar() && baz()) myInt++; beats nested if's any day)
    • 嗯? & 用于按位与运算。不过,副作用很有趣。
    • 在 C 和 C++ 时代是的,但在 C# 规范中 & 充当逻辑与(其中 && 是条件与),按位与(如果整数值用作操作数) ,最后它可以在不安全的上下文中用作一元运算符(返回其操作数的地址)。
    【解决方案2】:

    不,if 条件下的方法调用没有任何问题。实际上,这可能是让您的代码更具可读性的好方法!

    例如,写起来更简洁:

    private bool AllActive()
    {
        return x.IsActive && y.IsActive && z.IsActive;
    }
    
    if(AllActive())
    {
        //do stuff
    }
    

    比:

    if(x.IsActive && y.IsActive && z.IsActive)
    {
        //do stuff
    }
    

    【讨论】:

    • 为什么第一个选项会更干净?如果我只需要检查一次,为什么还要为它写一个额外的函数呢?
    • 主要是清晰,因为更容易理解您正在检查的条件。 “AllActive()”在快速查看代码时更容易理解。
    • 它增加了可读性,允许您在未来封装更复杂的复合评估。我有简单的 if 语句很快就变得非常难看,尤其是当你开始结合 ifs 和 ors 时。
    • 我也觉得这更清楚,假设 AllActive() 是一个有用且具有描述性的名称。
    • 这是经典的马丁福勒重构
    【解决方案3】:

    尽管它们很有用,但序列点可能会令人困惑。除非您真正理解这一点,否则 Method2() 可能根本不会被调用尚不清楚。另一方面,如果您需要调用这两个方法并且它们必须返回 true,您会写什么?你可以去

    bool result1 = Method1();
    bool result2 = Method2();
    if (result1 && result2)
    {
    }
    

    或者你可以选择

    if (Method1())
        if (Method2())
        {
        }
    

    因此,恕我直言,我想您的问题的答案是,不,尽管行为将是您所描述的,但您的意思并不完全清楚。

    【讨论】:

    • 我不同意。不知道布尔运算符是如何工作的不是用可读性较差的代码替换的借口。
    • 我同意斯波尔森的观点。利用短路评估是一个非常常见的习语,读起来更好,不应该让任何人感到困惑。
    • 虽然我大体上同意,但“不应该”并不总是评估为“不应该”。他的担忧是有道理的,我认为他提出这些问题是正确的,尤其是在 OP 问题的背景下。 +1。
    • 进一步澄清:对于新的、经验不足的开发人员来说,这并不总是很清楚。短路时的老帽子可能会觉得很舒服,根本不考虑它。其他的,没有那么多。但是,如果您愿意的话,“新手”可能会无意中尝试修复代码并产生意想不到的结果。
    • 除非我记错了,否则第二个例子只会在 Method1() 返回 true 的情况下执行 Method2()……那不就是短路吗?
    【解决方案4】:

    如果方法是纯(无副作用)函数,我只会推荐它。

    【讨论】:

      【解决方案5】:

      正如大家所说,以这种方式做事并没有什么“错误”,而且在许多情况下,您所做的正是该语言的设计目标。

      但是,请记住,为了可维护性,如果 Method2 有副作用(即,它改变了某些状态),那么这个函数没有被调用可能并不明显(一个好的程序员通常会知道,但即使优秀的程序员有时会放屁)。

      如果短路表达式有某种副作用,那么严格从维护的角度来看,将语句分开可能更具可读性。

      【讨论】:

      • 好电话。通常最好使这些类型的评估函数完全确定。一个好的方法是使它们成为静态的,并且只将值类型作为参数。这并不总是可能的,但它保证没有副作用。
      【解决方案6】:

      在我看来不错,如果之前的条件失败,if() 块中的多个子句会短路。

      【讨论】:

        【解决方案7】:

        应该没有问题。

        正常的行为是 Method1() 将执行,如果返回 true Method2() 将执行,根据 Method2() 返回的内容,您可能/可能不输入 if() 语句。

        现在,这假设编译器生成的代码以这种方式执行。如果你想绝对确定除非 Method1() 返回 true,否则 Method2() 不会执行,你可以这样写

        if( Method1() )
        {
          if( Method2() )
          {
            // do stuff if both methods returned TRUE 
          }
        }
        

        但是,我一直观察到您的代码会按预期运行,所以这可能没有必要。

        【讨论】:

        • 很高兴知道,我在使用 Visual Studio 时一直观察到这一点,我不确定它在语言中是否是标准的。
        【解决方案8】:

        没有错。

        实际上...我不会将它们命名为 Method1 和 Method2。更具描述性的东西。也可能是被动的声音(比如 StuffHasHappened 或 DataHasLoaded)

        【讨论】:

        • 来吧,我总是调用我的方法 Method_MethodNr_MethodFlavor_MethodColor_MethodShape
        • 谁需要一个臭名昭著的类图。对于使用鸡尾酒餐巾纸、椒盐卷饼和花生来模拟我的系统,我持教条主义的态度。
        【解决方案9】:

        对我来说看起来不错,但有一些警告......这不是适用一揽子规则的那种事情。

        我的指导方针是:

        • 如果方法名很短,而且数量不多,那就没问题了。
        • 如果您在if 语句中有太多的语句/方法调用,您很可能在比较多个“集合”的事物。打破这些“集合”并引入临时变量。
        • “太多”是主观的,但通常超过 3 个左右
        • 当我说“方法名称很短”时,我指的不仅仅是名称,还有它们所采用的参数。基本上是某人阅读它所需的努力。例如if( Open(host) )if( WeCouldConnectToTheServer ) 短。所有这些项目的总大小就是归结为。

        【讨论】:

          【解决方案10】:

          我个人会考虑

          if(Method1() && Method2())
          {
              // do stuff if both methods returned TRUE
          }
          

          是一种不好的做法。是的,它适用于当前环境,但也可以

          if(Method1())
          {
            if (Method2())
            {
              // do stuff if both methods returned TRUE
            }
          }
          

          但它适用于所有环境吗?未来,可能是非微软的 C# 编译器会以这种方式工作吗?如果您的下一份工作涉及另一种语言,而这两种方法都将被调用,该怎么办?我不会依赖那个特定的构造,不是因为它是错误的,而是因为它不能解决任何严重的问题,而且将来可能会出错

          【讨论】:

          • '未来的 [...] C# 编译器会以这种方式工作吗?' ECMA C# 规范说“x && y 对应于 [...] x & y,除了 y 仅在 x 为真时评估”;不服从的编译器与当条件评估为假而不是真时进入“if”块的编译器一样坏!不用担心。
          • Java、C 和 C++ 中也有同样的行为。以我的经验,大多数语言都有短路和运算符。逻辑运算符应该是您在学习一门新语言时首先要了解的内容之一,学习它们应该包括它们的短路行为。
          • @Cowan:不兼容的解释器和编译器是生活中的事实,而不是可以忽略的边缘条件。询问网络开发人员。或者,询问 C++ 程序员 msdn.microsoft.com/en-us/library/2tb15w2z.aspx
          • @Caleb:当我从大学毕业开始我的第一份工作时,我已经习惯了 Java、C/C++ 和 C#,所以我认为 VB.Net 也可以工作。不是这样! visualbasic.about.com/od/usingvbnet/l/bldykvbnetlogop.htm 在 VB.Net 中,无论如何都要对这两个表达式求值,而 AndAlso 的作用类似于 &&
          • 如果您有时间学习该语言的所有特性,那么您就不会被微小的差异所绊倒,但在现实世界中您并不总是有这种选择,所以越少在阅读或编写您不太了解的语言时必须做出的假设
          猜你喜欢
          • 2013-04-20
          • 1970-01-01
          • 1970-01-01
          • 2022-10-23
          • 1970-01-01
          • 1970-01-01
          • 2014-10-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多