其中哪一个更快/更好?
这一个:
List<User> list = new List<User>();
User u;
foreach (string s in l)
{
u = new User();
u.Name = s;
list.Add(u);
}
或者这个:
List<User> list = new List<User>();
foreach (string s in l)
{
User u = new User();
u.Name = s;
list.Add(u);
}
我的新手开发技巧告诉我第一个更好,但我的一个朋友告诉我错了,但不能给我一个很好的理由为什么第二个更好。
性能有什么不同吗?
答案 0 :(得分:96)
在性能方面,两个示例都编译为相同的IL,因此没有区别。
第二个更好,因为如果u
仅在循环中使用,它会更清楚地表达你的意图。
答案 1 :(得分:14)
在任何情况下,最好的方法是使用一个带有Name的构造函数...或者,否则,使用大括号表示法:
foreach (string s in l)
{
list.Add(new User(s));
}
或
foreach (string s in l)
{
list.Add(new User() { Name = s });
}
甚至更好,LINQ:
var list = l.Select( s => new User { Name = s});
现在,虽然你的第一个例子在某些情况下可能会在不知不觉中更快,但第二个例子更好,因为它更具可读性,编译器可能会丢弃变量(并完全省略它),因为它不会在{{{ 1}}的范围。
答案 2 :(得分:6)
声明不会导致任何代码被执行,因此这不是性能问题。
第二个是你的意思,如果你是第二种方式,你不太可能犯一个愚蠢的错误,所以使用它。始终尝试在必要的最小范围内声明变量。
此外,更好的方法是使用Linq:
List<User> users = l.Select(name => new User{ Name = name }).ToList();
答案 3 :(得分:5)
每当你对性能提出疑问时,唯一要做的就是测量 - 围绕测试运行循环并计时。
要回答你的问题 - 不测量:-)或者查看生成的ilasm - 任何差异在有意义的迭代次数中都不会引人注意,并且代码中最昂贵的操作可能是用户分配几个数量级,所以专注于代码清晰度(正如你应该的那样)和2。
哦,已经很晚了,我想我只是想说不要担心这类事情,或者陷入这样的细节。
ķ
答案 4 :(得分:1)
第二个更好。您的意思是在每次迭代中都有一个新用户。
答案 5 :(得分:1)
从技术上讲,第一个示例将节省几纳秒,因为不必移动堆栈帧来分配新变量,但这是一个很小的CPU时间你不会注意到它,如果是编译器并没有优化任何差异。
答案 6 :(得分:1)
在这种情况下,第二个版本更好。
通常,如果只需要访问迭代体内的值,则选择第二个版本。另一方面,如果有一些最终状态,变量将保持在循环体之外,然后声明然后使用第一个版本。
答案 7 :(得分:0)
表现应该没有令人难以置信的差异。
答案 8 :(得分:0)
另一个如上所示的参考:
答案 9 :(得分:0)
我去验证了这个问题。
(?:<[^>]+>)?
CIL泄漏出只有变量获得不同的编号。
所以我准备了一些本来应该更好的东西。
namespace Test
{
class Foreach
{
string[] names = new[] { "ABC", "MNL", "XYZ" };
void Method1()
{
List<User> list = new List<User>();
User u;
foreach (string s in names)
{
u = new User();
u.Name = s;
list.Add(u);
}
}
void Method2()
{
List<User> list = new List<User>();
foreach (string s in names)
{
User u = new User();
u.Name = s;
list.Add(u);
}
}
}
public class User { public string Name; }
}
CIL没有区别。
正如已经指出的那样,声明不是分配的,因此不存在性能损失。
namespace Test
{
class Loop
{
public TimeSpan method1 = new TimeSpan();
public TimeSpan method2 = new TimeSpan();
Stopwatch sw = new Stopwatch();
public void Method1()
{
sw.Restart();
C c;
C c1;
C c2;
C c3;
C c4;
int i = 1000;
while (i-- > 0)
{
c = new C();
c1 = new C();
c2 = new C();
c3 = new C();
c4 = new C();
}
sw.Stop();
method1 = method1.Add(sw.Elapsed);
}
public void Method2()
{
sw.Restart();
int i = 1000;
while (i-- > 0)
{
var c = new C();
var c1 = new C();
var c2 = new C();
var c3 = new C();
var c4 = new C();
}
sw.Stop();
method2 = method2.Add(sw.Elapsed);
}
}
class C { }
}