通过我昨天发布的一个问题,很明显,在循环之外声明一个变量并在其中实例化它没有性能优势,只需将声明移动到循环内部,因此声明和实例化同时完成。但实例化呢?请考虑以下两个选项。
//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
}
就本问题而言,关键假设是:
问题:哪种情况更好,哪种选择更好?
这篇文章的答案(尽管是关于声明,而不是实例化)似乎表明了后者:Declaring variables inside or outside of a loop
我的想法:
答案 0 :(得分:3)
哪种表现更好,哪种选择更好?
根据您的问题,如果只需要一个Person
实例,那么没有合理的理由将其反复实施
在循环内。在循环外部分配一次并在内部使用。
关于基本类型,您应该区分值类型(int
,long
,double
)和引用类型(string
)。值类型在堆栈上分配,而引用类型在堆上分配。因此,对于Person
类,我们必须在堆内分配适当的字节数,而在堆栈上分配int
是一个更快的分配。
除了最佳做法之外,如果您想知道两者中哪一个具有更好的性能,请对代码进行基准测试。这是在我的英特尔酷睿i5 M430上使用.NET Framework 4.5,VS2013在Debug Mode
中运行的输出:
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
答案 1 :(得分:1)
如果你做了10次,那么它的性能要低于你只做一次,因此单个实例化效率更高。如果您只需要一个实例,那么将对象初始化为多个时间也是没有意义的。这也可能有副作用,可能会使事情变得更糟。
因此,如果循环中没有改变,那么总是在循环之外声明并初始化它。这也将提高可读性,因为每个人都可以立即看到此对象很可能在以下循环中不会改变。
Person p = new Person("John", 35);
while (_doWork)
{
//work that involves reading (not writing to) p
}
如果必须在循环中创建对象,则应在循环中声明它。但不是因为它性能更高,而且更具可读性。