Declaring a variable inside or outside an foreach loop: which is faster/better?

Viewed 51241

Which one of these is the faster/better one?

This one:

List<User> list = new List<User>();
User u;

foreach (string s in l)
{
    u = new User();
    u.Name = s;
    list.Add(u);
}

Or this one:

List<User> list = new List<User>();

foreach (string s in l)
{
    User u = new User();
    u.Name = s;
    list.Add(u);
}

My newbie-developing skills tells me the first one is better, but a friend of mine tells me im wrong, but could not give me a good reason why the second one is better.

Is there any difference in performance at all?

10 Answers

Performance-wise both examples are compiled to the same IL, so there's no difference.

The second is better, because it more clearly expresses your intent if u is only used inside the loop.

In any case, the best way would be to use a constructor that takes a Name... or, otherwise, exploit curly-brace notation:

foreach (string s in l)
{
    list.Add(new User(s));
}

or

foreach (string s in l)
{
    list.Add(new User() { Name = s });
}

or even better, LINQ:

var list = l.Select( s => new User { Name = s});

Now, while your first example could, in some cases, be unperceptibly faster, the second one is better because it's more readable, and the compiler may discard the variable (and omit it altogether) since it's not used outsid the foreach's scope.

A declaration does not cause any code to be executed, so it's not a performance issue.

The second one is what you mean, and you're less likely to make a stupid error if you do it the second way, so use that. Always try to declare variables in the smallest scope necessary.

And besides, the better way is to use Linq:

List<User> users = l.Select(name => new User{ Name = name }).ToList();

Whenever you've a question about performance, the only thing to do is measure - run a loop around your test and time it.

To answer your question - without measuring :-) or looking at the generated ilasm - any difference wouldn't be noticeable in a meaningful number of iterations and the most expensive operation in your code there is likely to be the user allocation by a few orders of magnitude, so concentrate on code clarity (as you should in general) and go with 2.

Oh, its late and I guess I'm just trying to say don't worry about this sort of thing or get caught up in details like this.

K

The 2nd one is better. You are meaning to have a new user in each iteration.

Technically, the first example will save a few nanoseconds because the stack frame will not have to be moved to allocate a new variable, but this is such a tiny amount of CPU time you won't notice it, that's if the compiler doesn't optimize any difference away anyays.

In this scenario, the second version is better.

In general, if you only need to access the value within the body of the iteration, then choose the second version. On the other hand, if there is some final state the variable will hold beyond the body of the loop, then declare then use the first version.

I went to verify this issue.

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 spills out that only variables get a different numbering.

enter image description here

So I prepared something what was supposed to be much better one.

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 { }
}

CIL shows no difference.

enter image description here

As was already pointed out declaration is not allocation so there is no performance penalty on it.

Test

namespace Test
{
  class Foreach
  {
    string[] names = new[] { "ABC", "MNL", "XYZ" };

    public TimeSpan method1 = new TimeSpan();
    public TimeSpan method2 = new TimeSpan();

    Stopwatch sw = new Stopwatch();

    void Method1()
    {
      sw.Restart();

      List<User> list = new List<User>();
      User u;

      foreach (string s in names)
      {
        u = new User();
        u.Name = s;
        list.Add(u);
      }

      sw.Stop();
      method1 = method1.Add(sw.Elapsed);
    }

    void Method2()
    {
      sw.Restart();

      List<User> list = new List<User>();

      foreach (string s in names)
      {
        User u = new User();
        u.Name = s;
        list.Add(u);
      }

      sw.Stop();
      method2 = method2.Add(sw.Elapsed);
    }
  }

  public class User { public string Name; }

There should be no percievable difference in performance.

Related