循环中哪个更快:调用属性两次,或者存储属性一次?

Ste*_*ers 5 c# performance

这更像是一个关于性能的学术问题,而不是一个现实的"我应该使用什么",但我很好奇,因为我根本不涉及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.

And*_*ell 9

在我的测试中,你的第一个选择明显更快.我是这样的翻转翻牌!但是说真的,我对原始测试中的代码做了一些评论.这是更新的代码,显示选项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)


Meh*_*ari 7

大多数情况下,您的第二个代码段应该至少与第一个代码段一样快.

这两个代码片段在功能上并不相同.不保证属性在各个访问中返回相同的结果.因此,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)