这真的是一个改进吗(当内部作用域处于循环中时,将var移动到内部作用域)



Resharper建议这些变量:

List<string> senderDeviceIDList;
string senderDeviceID;
. . .
foreach (var item in PlatypiIds)
{
senderDeviceIDList = await GetSenderDeviceIDForSenderID(item);
senderDeviceID = senderDeviceIDList[0];

可以在内部范围中声明,如下所示:

foreach (var item in PlatypiIds)
{
List<string> senderDeviceIDList = await GetSenderDeviceIDForSenderID(item);
string senderDeviceID = senderDeviceIDList[0];

但这真的"更好"吗?这难道不会导致vars被声明N次(每个foreach循环一次)吗?

在性能或内存分配方面没有任何好处,因为if作用域内部的变量外部的变量是在IL中声明的。

唯一的好处是变量范围的本地化。将它移动到使用它的范围,这带来了好处,比如:

  • 容易重构(可能是最重要的)

  • 可读性。如果您在作用域内看到变量,您就知道它只在该作用域内使用;如果您看到某个变量显然不在作用域中,您就会知道更改它可能会影响代码的其他部分。因此,改变它会带来一些潜在的危险。

简而言之,这是关于您正在编写的代码的可读性和可用性,不会带来任何性能或内存消耗方面的好处。

这难道不会导致变量被声明N次(每个foreach循环一次)吗?

从逻辑上讲,从概念的角度来看,是的,,这就是重点!从逻辑上讲,它们每个循环存在一次,在循环的范围之外没有任何意义。

作为一个实现细节,不,它不会导致创建多个局部变量。该方法只有一个变量,在一般情况下(以及允许的情况下)将重复使用。有一些特殊情况,例如使用匿名方法关闭变量时,它不能重用变量。

请注意,由于C#强制您在使用所有局部变量之前对其进行初始化,运行时甚至不负责在每次循环后清除这些变量,因此编译器不会允许您重复使用之前的垃圾(除非您在循环开始时将其显式初始化为默认值)。

不管怎样,每次迭代都要为这些对象分配一次实例,在初始方法中唯一不同的是,您只声明一次引用,而不是像第二个例子中那样每次迭代。

如果您需要在foreach循环(毛茸茸的)结束时使用这些处于最终状态的对象,那么您可能需要使用第一种方法。

有时利益是存在的。

如果生成的数组很大,那么将其移动到内部作用域(即减少作用域和生存期)可能会阻止它转移到以后的垃圾收集代,并在明显延迟的情况下进行垃圾收集。


决定解释我的旧答案[在对投票结果感到惊讶后],并部分放弃我的话(27.10.2021)

详细信息#0。
您的两个选项在可见性范围和生存期方面有所不同。在";对于";循环的寿命从声明开始,直到该循环的},即直到每个迭代结束这意味着变量在每次迭代结束后都不存在,直到它到达下一次迭代的声明行

并且在"外部声明一个变量;对于";循环在方法体的整个持续时间内都存在(我假设在第一个示例中,它是在某个方法体的顶层声明的)。

好吧,它会影响什么?

变量可以表示指向对象的指针。只有当至少有人指向物体时,物体才会存在。因为如果没有人指着他们,怎么会有人提到他们呢?反之亦然——如果有人指向一个物体,它可能在未来的某个时候指向它,所以它必须活着。这正是垃圾收集器(GC)的逻辑。

因此,当您离开指向某个对象的变量的可见性范围时,GC可以停止考虑该指针。如果这个对象只有一个指向它自己(你的变量)的指针,那么这个对象就已经不存在了,因为没有人指向它。然而,它仍然以占用的内存为单位存在-它是堆中的一个垃圾,等待GC被收集(在下一次垃圾收集运行时或以后-由GC决定何时释放内存)。

回到您的选项-在方法执行过程中,这些选项在是否允许GC收集变量所指向的对象方面存在差异。只要垃圾收集随时可能发生,将变量声明移动到内部范围只会增加该对象被收集的概率。

啊啊。。99.9%的时候你不应该担心,因为这个物体无论如何都会在未来的某个时候被收集起来但是

细节#1

否";但是";。真的:)

Dunno,我可能在2016年就错了,认为LOH(大型对象堆)中的对象也有代,所以允许GC以多快的速度收集它们是很重要的,因为代越高,它的收集就越罕见。因此,第2代对象是寿命非常长的对象。现在情况并非如此(请参阅文档)-LOH对象在其整个生命周期中都是第2代对象。所以,不要急于用变量来LOH对象——你已经迟到了:)

即使这些对象很大,但对于LOH来说还不够大,在找到必须调查此事的证据(内存占用和性能)之前,您可能仍然不应该担心。

道德
所以,我的答案应该是有时利益是存在的[但可以忽略不计]

指定正确的范围首先对你自己和你的队友有帮助,而不是一个花哨的表演技巧。

最新更新