a = b = c 编码规范

3

我负责制定编码规范和进行代码审查。

我在我们的源代码中发现了这样的内容:

object.Property = myVar1 = myVar2;

我个人不这样做,因为我觉得它很令人困惑。我看到这个,就想把它读成这样:

object.Property = myVar1 == myVar2;

现在我知道它在做什么:它将myVar分配给myVar2,然后将object.Property分配给myVar2。编码标准文档没有明确规定是否可以这样做。但是它确实指出不要在if语句中分配变量。我想我的问题是,它的风格是否够糟糕,以至于不应该这样做?我不喜欢制定代码规范政策“只因为我这么说”。经过编辑更好地解释我的理解。

代码是为人类阅读而设计的,很少用于计算机执行。如果有歧义,请修复它 :) - Jesus Ramos
正如你所说,这很令人困惑... 这是我把它列为要避免的事情的一个很好的理由。 - Fabio
@Mehrdad现在记不起引用了:P - Jesus Ramos
@Jesus:这是来自SICP。:P 可能值得一提。 :) - user541686
@Mehrdad 是的,我忘记了源代码,谢谢。 - Jesus Ramos
1
必读Lippert博客文章:http://blogs.msdn.com/b/ericlippert/archive/2010/02/11/chaining-simple-assignments-is-not-so-simple.aspx - Joel Rondeau
7个回答

8

我总是将等式表达式用括号括起来:

object.Property = (myVar1 == myVar2);

这表明这不是一个任务。

7

这种所谓的“链式赋值”确实具有争议性,并且在SO上有很多相关问题。

正如您所知,这是赋值作为表达式而不是语句的副产品,对许多人来说可能会令人困惑。

在许多语言中,这对于新手来说有些危险。在使用[]构造空数组对象的语言中,编写

a = b = []

使ab引用同一个对象。初学者往往认为这会创建两个独立的空数组,可以分别填充。然而不是这样!在C#中,相当于:

a = b = new SomethingOrOther();

可以说这种情况发生的可能性要小得多,因为在声明时更有可能初始化ab,这样的双重赋值也会更加罕见。此外,C#程序员更有可能看到这种明显的共享。

禁止这种操作有如下三个好处:

  1. 完全没有必要。
  2. 容易出现错误(例如上文中的数组示例)。

当你遇到容易出错的结构时,应该避免使用它们,因为避免使用它们可以避免特定的错误。虽然在C#中,这种情况可能比其他语言要少出错得多。


1
然而,人们犯数组错误与C#完全无关... - user541686

2

在C#中,这通常不是什么需要担心的事情。

除非您的变量是bool(在这种情况下,无论如何都应将其分成两个语句),否则这不会出错 -- 这两种情况只有其中之一会正确工作,因此没有"意外地"省略或输入额外的=的危险。

结论:不要担心非布尔类型的情况。


2
首先,你不假设“我的方式就是正确的”,我向你致敬。这种问题非常主观,开发人员会有不同(通常是强烈的)意见。
我会说,我尽量避免令人困惑的代码,但像这样的语句(在某些情况下)可以将大量语句折叠成较少的语句,使代码更易读。并非总是如此,但我认为有时候是这样的。
我的意见是不要在编码标准中排除这种语句,并尽可能包容不同的编码风格(除了明显难以阅读或令人困惑的代码)。
我参与了许多比我想象的“编码标准”讨论,我发现它们往往比它们旨在解决的问题引起更多的摩擦。

谢谢,我尽力记住“编码标准”实际上存在的目的是为了给我们的项目带来一定的一致性,作为开发人员,我们可以期望这种一致性。我不想就“我的意见与你的意见”展开学究式的讨论。 - Matthew Doyle
是的,很高兴看到人们在思考这种事情! - jschorr

2

我遇到想要使用a = b = c的情况非常少,所以我会将其写成两个单独的语句。(这对我来说通常也是可以的,因为我喜欢在可能的情况下不重新分配变量,仅在声明时进行赋值,并且每个变量声明只声明一个变量。)

然后,如果我遇到a = b == c,我会将其视为“将等式的结果分配给a”,并且甚至不会再想一次(因为我的编码风格不包括a = b = c)。

然而,在C#中,这种错误被最小化了,因为除了处理布尔类型(对于a、b和c),编译器会抱怨类型不匹配。

祝编码愉快。


1
现在我知道它正在做什么:它将myVar赋值为myVar2,然后将object.Property赋值给myVar1。
您的理解是不正确的,编译器不会这样做。因为“赋值表达式”返回一个值,因此,在您的示例中,“object.Property”被分配为赋值表达式“myVar1 = myVar2”的返回值。而不是将“myVar2”分配给“myVar1”,然后将“myVar1”分配给“object.Property”。
因此,在您提供的两个语句之间没有混淆。但是,如果您的变量类型不同,则应使用“括号”使您的代码易读。
object.Property = myVar1 == myVar2;

1

由于这涉及到编码风格,因此这非常取决于我的个人看法。

几乎任何语言特性都可以被视为令人困惑或精妙,这取决于开发者。有些人认为运算符重载(或泛型、闭包、高阶函数等)是通往地狱的道路,而其他人则认为它是创建简洁易读代码的好工具。

如果这是您代码库中的常见模式,则您的开发人员可能已经熟悉了该模式的语义。在这种情况下,我认为反对该模式可能会产生反效果。

如果这是您代码库中不常见的模式,则这可能是一种令人困惑的模式,因此建议反对并搜索使用该模式的位置,并考虑进行重构。


是的,这就是我现在的情况...这是我第一次看到它,想不出为什么不能接受它作为可行的解决方案。最终,我不会对此发表任何意见,因为这并不常见,我更希望我的开发人员遵循更大的样式标准,而不是被这种东西所困扰。 - Matthew Doyle

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