从编译后的角度(而不是编码语法的角度)来看,在 C# 中,一行发生的一组操作与多行发生的一组操作在编译后的代码中是否有任何实际差异?
这个
object anObject = new object();
anObject = this.FindName("rec"+keyPlayed.ToString());
Rectangle aRectangle = new Rectangle();
aRectangle = (Rectangle)anObject;
对比这个。
Rectangle aRectangle = (Rectangle)this.FindName("rec"+keyPlayed.ToString());
我想知道,因为似乎有一种观点认为使用最少的线数更好,但是我想了解这是否是因为有切实的技术好处,或者是否在某些时候有切实的好处,或者是否确实是出于可量化的原因?
行数并不重要;如果代码是等效的(你的不是),IL 将是相同的。
实际上,除非我们知道
FindName
返回什么,否则我们无法正确回答 - 因为通过转换为 object
您可能会引入“盒子”操作,并且您可能会更改 conversion 操作(或者可能被动无操作强制转换)转换为主动双重强制转换(强制转换为 object
,强制转换为 Rectangle
)。现在,为了简单起见,我假设 FindName
返回 object
。如果您使用过 var
,我们一眼就知道您的代码没有更改类型(盒子/强制转换/等):
var anObject = this.FindName("rec"+keyPlayed.ToString());
在发布模式(启用优化)下,编译器将删除大多数设置后立即使用的变量。上面两行之间最大的区别是第二个版本不会创建和丢弃
new object()
和 new Rectangle()
。但如果您没有这样做,代码将是等效的(再次假设 FindName
返回 object
):
object anObject;
anObject = this.FindName("rec"+keyPlayed.ToString());
Rectangle aRectangle;
aRectangle = (Rectangle)anObject;
如果您重复使用该变量(在这种情况下,编译器不一定会删除它),并且该变量被 lambda/anon 方法“捕获”,或者在
ref
中使用,则存在一些微妙之处/out
。如果编译器/JIT 选择纯粹在寄存器中执行操作而不将其复制回变量(寄存器具有不同(更大)的宽度,即使对于像 这样的“固定大小”数学),某些数学场景的一些更微妙之处float
)。
我认为您通常应该致力于使代码尽可能具有可读性,有时这意味着将代码分开,有时意味着将其放在一行上。以可读性为目标,如果性能成为问题,请使用分析工具来分析代码并在必要时重构它。
编译后的代码可能没有任何差异(也许启用了优化),但也要考虑可读性:)
在您的示例中,一行上的所有内容实际上比单独的行更具可读性。你想要做的事情立刻就显而易见了。但其他人可以很快指出反例。因此,请运用您的良好判断力来决定走哪条路。
有一种重构模式更喜欢调用临时变量。遵循这种模式可以减少代码行数,但会使交互式调试变得更加困难。
两者之间的一个主要实际问题是,在调试时,将各个步骤放在不同的行上并将结果传递给局部变量会很有用。
这意味着您可以清楚地单步执行给出最终结果的不同代码位并查看中间值。
当您构建优化时,编译器将删除这些步骤并使代码高效。
托尼
您的示例存在实际差异,因为您在第一段代码中创建了不使用的对象和值。
编写该代码的正确方法是这样的:
object anObject;
anObject = this.FindName("rec" + keyPlayed.ToString());
Rectangle aRectangle;
aRectangle = (Rectangle)anObject;
现在,它与单行版本之间的区别在于您又声明了一个局部变量。在大多数情况下,编译器可以对其进行优化,以便生成的代码无论如何都是相同的,即使它实际上在生成的代码中使用了一个以上的局部变量,与您在该代码中执行的任何其他操作相比,这仍然可以忽略不计。
对于这个例子,我认为单行版本更清晰,但是对于更复杂的代码,当然可以将其分成几个阶段更清晰。局部变量非常便宜,因此如果代码变得更清晰,您应该毫不犹豫地使用一些局部变量。