【问题标题】:I don't like this... Is this cheating the language?我不喜欢这个...这是在欺骗语言吗?
【发布时间】:2010-10-24 15:07:07
【问题描述】:

我已经多次看到类似以下的内容......我讨厌它。这基本上是“欺骗”语言吗?或者..您是否认为这是“好的”,因为始终首先评估 IsNullOrEmpty?

(我们可以争论一个字符串从函数中出来时是否应该为 NULL,但这不是真正的问题。)

string someString;
someString = MagicFunction();

if (!string.IsNullOrEmpty(someString) && someString.Length > 3)
{
    // normal string, do whatever
}
else
{
   // On a NULL string, it drops to here, because first evaluation of IsNullOrEmpty fails
   // However, the Length function, if used by itself, would throw an exception.
}

编辑: 再次感谢大家提醒我这个语言基础。虽然我知道它“为什么”起作用,但我不敢相信我不知道/不记得这个概念的名称。

(如果有人想要任何背景。我在解决由 NULL 字符串和 .Length > x 异常生成的异常时遇到了这个问题......在代码的不同位置。所以当我看到上面的代码时,除了其他一切,我的挫败感从那里接管了。)

【问题讨论】:

  • 这些类型的运算符被称为“条件运算符”是有原因的 - 来自 MSDN:“条件与运算符 (&&) 对其布尔操作数执行逻辑与,但仅计算其第二个操作数如有必要。” msdn.microsoft.com/en-us/library/2a723cdk(VS.80).aspx
  • 在 C++ 中,无法保证执行条件检查的顺序。在 C# 中是否有所不同?
  • 也许这是 [facepalm] 分类徽章的机会:P
  • 我真的不明白为什么这被否决了,因为这是一个合理的问题。有些人就是没有意识到这些事情,让他们该死的学习该死的精英!
  • 这是他们努力为我们提供 Spec# 中看到的 NonNullable 合约的原因之一

标签: c# syntax short-circuiting


【解决方案1】:

这并没有什么问题,因为您只是想确保不会出现空指针异常。

我认为这样做是合理的。

使用扩展程序可以使其更简洁,但基本概念仍然有效。

【讨论】:

  • 你能发布“带扩展”的示例吗?
  • 只是有一个扩展: public static bool IsNullOrEmpty(this string str) { return string.isNullOrEmpty(str); } 那你就可以全部 if (!someString.IsNullOrEmpty() && someString.Length > 3) { ... } 我觉得它看起来更干净,但基本上是一样的。
【解决方案2】:

这并没有错。

if(条件是从左到右评估的,所以像这样堆叠它们是完全可以的。

【讨论】:

    【解决方案3】:

    如果您问是否可以依赖“短路”关系运算符&&||,那么可以。

    【讨论】:

    • 不仅很好,而且我想大多数人会认为它是一种语言特性
    • 总是考虑到它可能会短路,所以它会运行得更快。
    • @KM - 几乎总是,但如果第二个操作数是在每种情况下都需要执行的方法,则不是。当然,有人会质疑这种在条件内执行的方法的优点。最好事先执行它并将结果保存在变量中。也就是说,我已经看到了这种情况,并且知道人们在试图弄清楚为什么该方法没有按预期执行时感到头疼。
    • 我不了解 C#,但在 Java 中也有非短路关系运算符。它们是相同的,只是它们由一个字符而不是两个字符组成,|&。无论如何,它们总是执行第二个操作数......(只要第一个操作数不引发异常)。
    • @TL 它们既是位运算符又是关系运算符,这取决于上下文。如果操作数是布尔值,那么您将得到一个非短路关系运算符。如果操作数是整数类型,你会得到一个按位运算符。我再次在这里谈论 Java,我不是 C# 程序员。它在 Java 规范中:java.sun.com/docs/books/jls/third_edition/html/…
    【解决方案4】:

    您正在利用一种称为短路的语言功能。这不是在欺骗语言,而是实际上完全按照设计使用的方式使用了功能。

    【讨论】:

    • -1:编写软件是一回事,维护它们是另一回事。当您的老板要求您立即更正现有代码时,您可以轻松克服这种情况。 2个if呢?或者评论说这里发生了什么?维护软件的人比编写软件的人聪明得多(我知道,我维护软件有一段时间了)。问题是:代码编写者认为每个人都和他们一样聪明。但是这是错误的。当你写代码时,请想想我们!我们必须阅读大量代码并在一分钟内做出反应,我们并不聪明!
    • @Sylvain,一致认为聪明的代码更难维护。然而,这段代码并没有试图变得聪明。它以预期的方式使用了众所周知的语言功能。此外,这不仅仅是 C# 的特性,它几乎是任何语言(C++、F#、VB.Net、C#、C 等)的特性。期望其他程序员理解这段代码的预期功能是完全合理的
    • +1 - 这是 C、C++、C#、Perl、Python、Ruby、PHP 中的一个非常标准的做法...
    • @Sylvain:如果您不了解专业工具的基础知识(而短路布尔运算符 基础),那么您不应该接触生产代码。
    • @Sylvain,就像其他人所说的那样,这是基本的。这就像不允许 x=Function1(Function2()) 或 x=(y+1)*3 因为它“不明显”。有些事情是所有程序员都应该知道的,短路就是其中之一。
    【解决方案5】:

    在我看来,这是有效的代码(虽然声明一个变量并在下一行分配它很烦人),但您可能应该意识到,您也可以在字符串是

    【讨论】:

      【解决方案6】:

      这是完全有效的,以这种方式使用它没有任何问题。如果您遵循该语言的记录行为,那么一切都很好。在 C# 中,您使用的语法是条件逻辑运算符,可以在 MSDN

      上找到它们的文档化bahviour

      对我来说,这与在同一语句中进行乘法和加法运算时不使用括号的情况相同,因为语言记录了乘法运算将首先执行。

      【讨论】:

      • 关于运算符优先级的事情:括号不仅仅用于分组操作,如果使用得当,它们也可以提高表达式的可读性。
      【解决方案7】:

      我觉得没问题 :) 你只是确保你没有访问 NULL 变量。 实际上,我总是在对变量进行任何操作之前进行此类检查(还有,在索引集合等时)——这样更安全,是最佳实践,仅此而已..

      【讨论】:

        【解决方案8】:

        此代码完全有效,但我喜欢使用 Null Coalesce Operator 来避免空类型检查。

        string someString = MagicFunction() ?? string.Empty;
        if (someString.Length > 3)
        {
            // normal string, do whatever
        }
        else
        {
           // NULL strings will be converted to Length = 0 and will end up here.
        }
        

        【讨论】:

        • 但是,这会改变变量的值,这并不总是可取的。
        【解决方案9】:

        在我看来,这是对逻辑短路的完全合理的使用——如果有的话,它是在欺骗 语言。我最近才从没有曾经短路的 VB6 回来,这真的让 很恼火。

        需要注意的一个问题是,您可能需要在 else 子句中再次测试 Null,因为 - 正如所写的那样 - 您将同时使用 Null 字符串和长度小于三个字符串.

        【讨论】:

        • VB6 没有短路操作符?哇,我听过人们开玩笑说它是脑死亡,但在语言中忽略这是一件非常愚蠢的事情......
        • 不。而 VB.Net 在这方面仍然是半瘫痪的,因为 And 和 Or 仍然没有短路。您必须使用 AndAlso 和 OrElse 才能短路。
        • 我做了 7 年的 VB 编程,改用 C#(已经在那里工作了 7 年),就在前几天不得不维护一个 VB 宏时,我被这个无短路的东西赶上了。没有短路的东西留在那里用于反向兼容,因为有些人会编写带有副作用的 if 语句(语句中的最后一个“测试”总是会运行)。这有多精神?
        • 认为这是向后兼容性(尽管有很多其他的根本性改变,以至于保留它似乎是一件愚蠢的事情),但我仍然可以哀悼。如果只有对副作用的依赖会有点成语……嗯,挑战的是写它们的人而不是我们之后的人……
        【解决方案10】:

        这是有道理的,因为默认情况下 C# 会短路条件,所以我认为可以利用它来发挥自己的优势。在 VB 中,如果开发人员使用 AND 而不是 ANDALSO,可能会出现一些问题。

        【讨论】:

        • 是的。虽然我很高兴他们添加了 AndAlso,并且现在总是使用它,但我希望他们只是修复了 And 的行为(对于 Or/OrElse 也是如此)。
        【解决方案11】:

        我认为这与这样的事情没有什么不同:

        INT* pNumber = GetAddressOfNumber();
        
        if ((pNUmber != NULL) && (*pNumber > 0))
        {
          // valid number, do whatever
        }
        else
        {
          // On a null pointer, it drops to here, because (pNumber != NULL) fails
          // However, (*pNumber > 0), if used by itself, would throw and exception when dereferencing NULL
        }
        

        它只是利用了语言中的一个特性。我认为,自从 C 开始以这种方式执行布尔表达式(或者任何一种语言首先使用它)以来,这种习惯用法就已经很普遍了。)

        【讨论】:

          【解决方案12】:

          如果是编译成程序集的 c 代码,不仅可以缩短正确的行为,而且更快。在机器语言中,if 语句的各个部分是一个接一个地计算的。不短路比较慢。

          【讨论】:

            【解决方案13】:

            编写代码对公司来说要花很多钱。但维护成本更高!

            所以,我同意你的观点:很可能这行代码不会被必须在 2 年内阅读并更正它的人立即理解。

            当然,他会被要求纠正一个严重的生产错误。他会到处搜索,可能不会注意到这一点。

            我们应该总是为下一个人编码,他可能不如我们聪明。对我来说,这是唯一要记住的事情。

            这意味着我们使用明显的语言特征并避免使用其他语言特征。

            一切顺利,西尔文。

            【讨论】:

            • 我的代码假设维护者会比我更聪明,也更缺乏经验。然而,我确实假设维护者不会被常见的、标准的语言结构所迷惑。如果您对短路运算符有任何问题,那么您就没有必要接触严重的错误。
            • 强烈同意David的观点。 “if (foo() && bar())” 结构非常标准,对于经验丰富的程序员来说,它实际上更清晰、更容易阅读。
            • 你应该是对的,但是自 2000 年以来,许多非计算机科学家被雇用来创建和维护重要的软件(在以前的任务中,C 函数有超过 4000 loc + 9 级缩进很常见)。这些人可能和任何人一样聪明,但在我们要求他们维护 C 代码之前,他们中的许多人从未读过有关 C 的书。最糟糕的是,当发现一个错误时,他们通常有很大的压力来立即纠正它——他们没有时间摆弄——代码必须非常清晰。反正短路是可以的,只要不是到处乱用就行。
            • @Sylvain:我不会为不懂编程的人编写代码。尤其是当他们的职责朝那个方向转变时,他们甚至没有足够的专业动力在自己的时间拿起一本关于 C 的书。
            • @Greg D. 你不是唯一一个!我目前试图了解一些优秀的 IQ 对许多设计模式做了什么,以便……保存简单的数据。 1 zillons 来源,高度继承树,完全没有评论,哇!什么男人的态度!此外,纠正一个简单的错误需要 2 或 3 天。他们是专业人士吗?您的电话...
            【解决方案14】:

            在大多数情况下,依靠短路是“正确的做法”。它导致代码更简洁,活动部件更少。这通常意味着更容易维护。在 C 和 C++ 中尤其如此。

            我会认真重新考虑雇用不熟悉(也不知道如何使用)短路操作的人。

            【讨论】:

              【解决方案15】:

              有点跑题了,但是如果你像这样在 vb.net 中使用相同的示例

              dim someString as string
              someString = MagicFunction()
              if not string.IsNullOrEmpty(someString) and someString.Length > 3 then
                  ' normal string, do whatever
              else
                  ' do someting else
              end if
              

              这会对一个空(无)字符串产生影响,但在 VB.Net 中,您将其编码如下,在 C# 中执行相同操作

              dim someString as string
              someString = MagicFunction()
              if not string.IsNullOrEmpty(someString) andalso someString.Length > 3 then
                  ' normal string, do whatever
              else
                  ' do someting else
              end if
              

              添加 andalso 使其行为方式相同,而且它的阅读效果更好。作为同时进行 vb 和 c' 开发的人,第二个 vb 显示登录名略有不同,因此更容易向某人解释存在差异等。

              毒药

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-07-06
                • 2015-09-15
                • 1970-01-01
                • 2010-11-20
                • 1970-01-01
                • 1970-01-01
                • 2015-04-03
                • 2020-01-03
                相关资源
                最近更新 更多