这更像是一个关于性能的学术问题,而不是一个现实的"我应该使用什么",但我很好奇,因为我根本不涉及IL,看看是什么构造的,我手边没有大数据集.反对.
那么哪个更快:
List<myObject> objs = SomeHowGetList();
List<string> strings = new List<string>();
foreach (MyObject o in objs)
{
if (o.Field == "something")
strings.Add(o.Field);
}
Run Code Online (Sandbox Code Playgroud)
要么:
List<myObject> objs = SomeHowGetList();
List<string> strings = new List<string>();
string s;
foreach (MyObject o in objs)
{
s = o.Field;
if (s == "something")
strings.Add(s);
}
Run Code Online (Sandbox Code Playgroud)
请记住,我真的不想知道string.Add(s)的性能影响(因为无论需要做什么操作都无法真正改变),只是设置每次迭代之间的性能差异(让我们看看)假设s可以是任何原始类型或字符串)每次迭代时调用对象上的getter.
在我的测试中,你的第一个选择明显更快.我是这样的翻转翻牌!但是说真的,我对原始测试中的代码做了一些评论.这是更新的代码,显示选项2更快.
class Foo
{
public string Bar { get; set; }
public static List<Foo> FooMeUp()
{
var foos = new List<Foo>();
for (int i = 0; i < 10000000; i++)
{
foos.Add(new Foo() { Bar = (i % 2 == 0) ? "something" : i.ToString() });
}
return foos;
}
}
static void Main(string[] args)
{
var foos = Foo.FooMeUp();
var strings = new List<string>();
Stopwatch sw = Stopwatch.StartNew();
foreach (Foo o in foos)
{
if (o.Bar == "something")
{
strings.Add(o.Bar);
}
}
sw.Stop();
Console.WriteLine("It took {0}", sw.ElapsedMilliseconds);
strings.Clear();
sw = Stopwatch.StartNew();
foreach (Foo o in foos)
{
var s = o.Bar;
if (s == "something")
{
strings.Add(s);
}
}
sw.Stop();
Console.WriteLine("It took {0}", sw.ElapsedMilliseconds);
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
大多数情况下,您的第二个代码段应该至少与第一个代码段一样快.
这两个代码片段在功能上并不相同.不保证属性在各个访问中返回相同的结果.因此,JIT优化器无法缓存结果(除了微不足道的情况),如果缓存长时间运行的属性的结果,它会更快.看看这个例子:为什么在读取richtextbox行时foreach比for循环更快.
但是,对于某些特定情况,例如:
for (int i = 0; i < myArray.Length; ++i)
Run Code Online (Sandbox Code Playgroud)
在哪里myArray是数组对象,编译器能够检测模式并优化代码并省略绑定检查.如果缓存Length属性的结果可能会更慢:
int len = myArray.Length;
for (int i = 0; i < myArray.Length; ++i)
Run Code Online (Sandbox Code Playgroud)