99

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 I'm wrong, but could not give me a good reason why the second one is better.

Is there any difference in performance at all?

Dale K
  • 25,246
  • 15
  • 42
  • 71
Marcus
  • 1,197
  • 1
  • 7
  • 14
  • Did you ever try the first method in the end? If user is a class, not a struct, in my understanding it would create a list containing the last user n times. – Frederik Steinmetz Feb 27 '23 at 11:08

10 Answers10

132

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.

dtb
  • 213,145
  • 36
  • 401
  • 431
  • 11
    Note that there *is* a difference if the variable is captured by a lambda expression or anonymous delegate; see [Outer Variable Trap](http://stackoverflow.com/q/3416758). – dtb Apr 29 '13 at 09:44
  • Can you explain why both are compiled to the same IL? I'm pretty certain that C# doesn't hoist variable declarations up to the top of the function like javascript does. – styfle May 30 '13 at 01:14
  • 4
    @styfle here's [the answer](http://stackoverflow.com/questions/1884906/declaring-a-variable-inside-or-outside-an-foreach-loop-which-is-faster-better#comment1785311_1884957) to your question. – David Sherret Apr 16 '14 at 20:39
  • 1
    Following Stack Overflow links provide more detailed answers: **1)** [Jon Hanna](https://stackoverflow.com/a/8536197/3613932) and **2)** [StriplingWarrior](https://stackoverflow.com/a/7383090/3613932) – user3613932 May 23 '17 at 03:44
14

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.

Tordek
  • 10,628
  • 3
  • 36
  • 67
  • 8
    Necrophilic comment of the day: "or even better, LINQ". Sure it's one line of code, and that makes us as developers feel good. But the four line version is FAR more understandable, and thereby maintainable. – Oskar Austegard May 22 '13 at 18:58
  • 5
    Hardly. With the LINQ version I know that what I'm doing is immutable, and it's working over every element. – Tordek May 23 '13 at 13:32
6

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();
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 2
    I love the line "Always try to declare variables in the smallest scope necessary." I think a single line can answer the question very well. – Manjoor Jul 02 '10 at 10:42
5

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.

Dale K
  • 25,246
  • 15
  • 42
  • 71
Kevin Shea
  • 920
  • 7
  • 12
  • thx for the tip, i think i will time some other stuff i've been woundering about aswell hehe :D – Marcus Dec 11 '09 at 00:22
  • If you want to go further with looking into what affects performance, look into using a code profiler. If nothing else, it will start to give you an idea of what type of code and operations take most time. ProfileSharp and EqatecProfilers are free and sufficient to get you started. – Kevin Shea Dec 11 '09 at 08:50
2

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; }
Yarl
  • 728
  • 1
  • 7
  • 26
1

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

Jarrett Widman
  • 6,329
  • 4
  • 23
  • 32
1

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.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • I'm pretty sure the CLR doesn't allocate "a new variable" on each iteration of a loop. – dtb Dec 10 '09 at 23:51
  • Well, the compiler may well optimize that away, but stack space has to be allocated for any variables in a loop. This would be implementation dependant and one implementation may simply keep the stack frame the same, while another (say Mono) could release the stack then recreate it on each loop. – Erik Funkenbusch Dec 10 '09 at 23:54
  • 18
    All local variables in a method (top-level or nested in a loop) are compiled to method-level variables in IL. The space for the variables is allocated before the method is executed, not when a branch with the declaration in C# is reached. – dtb Dec 11 '09 at 00:01
  • 1
    @dtb Do you have a source for this claim? – styfle Apr 17 '14 at 20:46
1

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.

csj
  • 21,818
  • 2
  • 20
  • 26
1

Another reference which looks like above:

http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/d43aaba5-a58b-4610-bea4-5bc5d6741f98

Sunil
  • 2,885
  • 5
  • 34
  • 41
0

There should be no percievable difference in performance.

Jacob Adams
  • 3,944
  • 3
  • 26
  • 42