将变量和值的顺序颠倒有什么好处吗?

6
我不是一个经验丰富的开发者。但我一直听说写代码的意图之一就是使其可读性更强。这只是一个小例子,但它让我感到困惑,我想了解是否有一些我没有看到的好处,因为我还是个新手。我正在审查一位资深开发者的代码,我看到了这样的代码:
如果 (0 == intValue)
再次强调,这只是一个小事情。在20行代码中出现了10次以上。但我们想要测试intValue的值,但我们在这里表达的却是我们想要测试0的值。对我来说,这与人们思考的方式相反,变得不太易读。有没有什么好的理由以这种方式编写代码?

7
不是在C#中,基本上这是从其他语言遗留下来的问题,其中if (intValue = 0)会静默编译但不会按照你的期望执行。我猜测你正在审查的开发者可能来自这样的语言背景。虽然这是主观的,但我同意你的观点:这种写法不够易读,最好按照更自然的顺序进行编写。 - Jon Skeet
7
不是用C#,基本上这是从其他语言遗留下来的问题,那些语言中if (intValue = 0)会静默编译通过,但并不会按照你的期望执行。我猜测你正在审查的开发者可能来自这样的语言背景。虽然这是主观的,但我同意你的观点:这种写法不够易读,最好按照更自然的顺序来编写。 - Jon Skeet
4
这被称为Yoda条件 - Martin Smith
4
这被称为Yoda条件 - Martin Smith
2
@MartinSmith:你是指“这被称为Yoda条件”吗? - dan04
显示剩余8条评论
2个回答

1
从历史上看,这在许多平台上为代码增加了一点安全性。想象一下,你以更“自然”的方式编写了条件:
if (intValue == 0)

有时候,在长时间的工作中,人的大脑会玩弄他们,很容易把任务误认为是平等。
if (intValue = 0)

这显然是错误的,但当你犯了这个错的时候,很难发现

除了明显的对 intValue 的意外改变之外,这还有一个不太明显的问题,即在许多平台上,它将始终导致 false,而不考虑预期的比较。这是因为对于大多数平台来说,赋值表达式的结果是被赋的值,并且允许将 0 值解释为 false有时,这第二个因素可以长时间隐藏这两个问题。

以相反(尤达)顺序编写表达式可以保护我们免受此影响,因为在几乎任何平台上,在赋值的左侧不能有字面量是不合法的。

值得庆幸的是,对于 C# 来说,这个问题要小得多。

使用C#,默认情况下,错误的代码会导致编译器错误,因为if(0)在开箱即用的情况下是不合法的。然而,可以构造一些例子使其编译通过:如果你正在使用布尔常量,如果这只是一个更大表达式的一部分,其中int结果是合法的,如果你定义了一个隐式转换到bool的方法等等。
我还想谈谈关于“自然”一词周围的引号。我使用它们是因为编程语言实际上并没有什么自然的东西。这些都是经过设计和人为构造的平台,如果有什么看起来自然的话,那是因为我们训练自己以这种方式看待它们。如果我们能训练自己将一个版本视为自然,我们也可以训练自己以同样的方式看待另一个版本。
出于这个原因,一些人仍然喜欢养成始终使用“安全”版本的习惯,即使在不需要的平台上,因为这有助于他们发现在可能仍然重要的平台上可能存在的错误。JavaScript在这里是一个常见的例子。
话虽如此,我仍然倾向于写不太安全的版本 :/

你是不是把问题误读成关于C语言了?因为在C#中,if (intValue = 0)是无效的语法。 - Blindy
2
我并没有把这个错误当作C语言。我只是试图解释模式的起源。但我看到有些混淆,所以我做了一些修改来澄清。 - Joel Coehoorn
2
我并没有把这个错误地理解为C。我只是试图解释这个模式的起源。但我看到了困惑,所以我做了一些修改来澄清。 - Joel Coehoorn
1
@dan04 - 在这种情况下,你会得到“警告 CS0665:条件表达式中的赋值始终是常量;你是否意味着使用 == 而不是 = ”。 - Martin Smith
1
在这种情况下,你会得到一个警告 CS0665:“条件表达式中的赋值始终是常量;你是否意味着使用 == 而不是 = ”。 - Martin Smith
显示剩余4条评论

1
在C#中,写这些不自然的语句真的是没有意义的,因为编译器已经会对非布尔检查发出错误。考虑以下代码:
int intValue = 5;
if (intValue = 6)
{
}

这会导致编译错误。
Error CS0029: Cannot implicitly convert type 'int' to 'bool'

原因很明显:intValue = 6 是一个赋值操作并返回一个整数值,这个值无法转换为bool。因此会出现编译错误。所以你会立即发现问题。
然而,对于boolean检查来说,情况就更加微妙了。考虑一下。
bool boolValue = true;
if (boolValue = false)
{
}

这次编译器发出了一个警告:
Warning CS0665: Assignment in conditional expression is always constant; 
did you mean to use == instead of = ?

为了避免忽视这个警告和产生意外的结果,可以将警告视为错误处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接