变量的作用域:在循环内部或外部实例化
本文关键字:内部 外部 实例化 循环 作用域 变量 | 更新日期: 2023-09-27 18:19:14
通过我昨天发布的一个问题,很明显,在循环之外声明一个变量并在循环内部实例化它,与简单地将声明移动到循环内部相比,没有性能优势,因此声明和实例化是同时完成的。但是实例化呢?考虑下面两个选项。
//OPTION 1:
while (_doWork)
{
Person p = new Person(name = "John", age = 35);
//work that involves reading (not writing to) p
}
//OPTION 2:
Person p = new Person(name = "John", age = 35);
while (_doWork)
{
//work that involves reading (not writing to) p
}
对于这个问题,关键的假设是:
- p在循环之外不需要
- p也不会被写入(因此结果方面,两者是相同的)
- 没有结果的原因为什么我们应该继续重新实例化p (p在两个选项中看起来是一样的)
问题:哪个性能更好,哪个选项是更好的实践?
这篇文章的答案(尽管是关于声明,而不是实例化)似乎表明后者:在循环内部或外部声明变量
My Thoughts:
- 对我来说,不断地重新安装它似乎是一种很大的浪费。对于基本类型可能没问题,但对于复杂类呢?
- int a = 0与int a = new int()相同,所以我猜上面的答案也适用于基本类型?
哪个是更好的性能,哪个选项是更好的实践?
根据你的问题,如果只需要一个Person
实例,那么就没有逻辑上的理由一次又一次地实例化它在循环内部。在循环外分配一次,在循环内使用。
关于基本类型,您应该区分值类型(int
, long
, double
)和引用类型(string
)。值类型在堆栈上分配,而引用类型在堆上分配。因此,对于Person
类,我们必须在堆中分配适量的字节,而在堆栈上分配int
是一个更快的分配。
除了最佳实践,如果您想知道两者中哪一个具有更好的性能,请对您的代码进行基准测试。这是在Debug Mode
与。net Framework 4.5, VS2013中运行的输出,在我的英特尔酷睿i5 M430上:
public class Person
{
public Person(string name, int age)
{
Age = age;
Name = name;
}
public int Age { get; set; }
public string Name { get; set; }
}
private static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
Person p = new Person("John", 35);
var age = p.Age;
var name = p.Name;
}
Console.WriteLine("Loop with inner allocation took {0}", m sw.Elapsed);
sw.Restart();
Person px = new Person("John", 35);
for (int i = 0; i < 1000000; i++)
{
var age = px.Age;
var name = px.Name;
}
Console.WriteLine("Loop with outter allocation took {0}", sw.Elapsed)
}
和结果:
Loop with inner allocation took 00:00:00.0708861
Loop with outter allocation took 00:00:00.0155522
如果执行某项操作10次,其性能会低于只执行一次,因此单次实例化更有效。如果只需要一个实例,那么多次初始化对象也是没有意义的。这也可能有副作用,可能会使事情变得更糟。
因此,如果它在循环中没有改变,则总是在循环外声明并初始化它。这也将增加可读性,因为每个人都可以立即看到这个对象在下一个循环中很可能不会改变。
Person p = new Person("John", 35);
while (_doWork)
{
//work that involves reading (not writing to) p
}
如果必须在循环中创建对象,则应该在循环中声明它。但不是因为性能更好,而是因为可读性更好。
阅读:https://softwareengineering.stackexchange.com/questions/56585/where-do-you-declare-variables-the-top-of-a-method-or-when-you-need-them