0

I make it simple (because i didn't find anything on Google, maybe because i don't know either what search).

What is the difference beetween this:

foreach(var x in g.GetList())
{
 code
}

and this:

IEnumerable<object> list = g.GetList();
foreach(var x in list)
{
 code
}

in terms of performance or in terms of best practices, or whatever?

Im Flash
  • 45
  • 1
  • 8

3 Answers3

0

These two pieces of code:

foreach(var x in g.GetList())
{
 code
}

and

IEnumerable<object> list = g.GetList();
foreach(var x in list)
{
 code
}

have only 1 difference, and that is that you placed the result of calling g.GetList() into a variable yourself.

IL-wise, what the compiler outputs, when you compile for RELEASE mode, will be 100% identical.

Here's a sample LINQPad program:

void Main() {  }

static void Method1()
{
    foreach (var x in g.GetList()) { }
}

static void Method2()
{
    IEnumerable<object> list = g.GetList();
    foreach (var x in list) { }
}

static class g
{
    public static IEnumerable<object> GetList() => new List<object>();
}

will produce this IL code for both Method1 and Method2:

IL_0000:  call        UserQuery+g.GetList
IL_0005:  callvirt    System.Collections.Generic.IEnumerable<System.Object>.GetEnumerator
IL_000A:  stloc.0     
IL_000B:  br.s        IL_0014
IL_000D:  ldloc.0     
IL_000E:  callvirt    System.Collections.Generic.IEnumerator<System.Object>.get_Current
IL_0013:  pop         
IL_0014:  ldloc.0     
IL_0015:  callvirt    System.Collections.IEnumerator.MoveNext
IL_001A:  brtrue.s    IL_000D
IL_001C:  leave.s     IL_0028
IL_001E:  ldloc.0     
IL_001F:  brfalse.s   IL_0027
IL_0021:  ldloc.0     
IL_0022:  callvirt    System.IDisposable.Dispose
IL_0027:  endfinally  
IL_0028:  ret

So there is no difference other than how you wrote the code.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
0

After it's clear that both are semantically identically, I only want to add that there are three practically reasons to prefer creating an additional variable over an inlined expression.

  1. It is more descriptive. People might better understand the value's purpose with a name. It particularly matters when the expression gets long and more difficult to read inline. Therefore, it might help skimming code. And no, it is not considered good coding style to replace the variable name with a comment. The difficulty about comments is, that their reference or scope inside code is not immediately clear, they can contain anything, and therefore disturb the reading flow inside code blocks, which is more annoying if less additional information is contained compared to the provided code.

  2. It allows more flexibility with code changes. You just can put additional code between a variable's definition and its usage and move the definition line up and down with simple keyboard short cuts. Whenever people believe in easier to understand = less to read (which is not generally true) they start to add additional nesting, hard-coded program structure, basically "readability optimization", which decreases the flexibility of changes and increases syntactic complexity (I personally find conventional Nim style to be a good example for that). Some coding standards therefore even disallow defining multiple variables in a single statement or with a single type/keyword.

  3. With a debugger, you have a better time figuring out the expression's value because you can set more subtle breakpoints and read out variable contents.

ChrisoLosoph
  • 459
  • 4
  • 8
-1

In the below code, you are directly calling the g.GetList() method in your foreach

foreach(var x in g.GetList())
{
 code
}

In the below code, You are assigned the g.GetList() method in a variable, then You are calling the variable in your foreach. Comparing with the first code, The performance vice, no difference. Just the compiler compile extra one line. that's all.

IEnumerable<object> list = g.GetList();
foreach(var x in list)
{
 code
}

But your first code may threw a null reference error if g.GetList(); method return null. So the best practice is check null condition before use the variable/method in foreach

IEnumerable<object> list = g.GetList();
if(list == null)
{
retur false;
}
foreach(var x in list)
{
 code
}

And must use real object instead of using object and dynamic data types due to type safe.

IEnumerable<Employee> list = g.GetList();// as per employee is your class name

Performance is very important for clients, But Standard and understandable coding's are important for developers. I hope you can understand what is am explained.

Ramesh Rajendran
  • 37,412
  • 45
  • 153
  • 234
  • "But your first code may threw a null reference error if g.GetList(); method return null" That exception is caused in both options. – MakePeaceGreatAgain Nov 15 '17 at 12:45
  • @HimBromBeere. Yes. Agree! That's why I have wrote new case with checking null exception. See the third option. – Ramesh Rajendran Nov 15 '17 at 12:48
  • There should be no difference at all in the compiled code in this case, assuming `g.GetList()` returns `IEnumerable`. – Lasse V. Karlsen Nov 15 '17 at 12:50
  • @LasseVågsætherKarlsen . But another developer need to check the method is return list of value or null. How we know if that method return null instead of `IEnumerable` – Ramesh Rajendran Nov 15 '17 at 12:52
  • Thank you for your explaination. I used IEnumerable for this example only. – Im Flash Nov 15 '17 at 13:42
  • Whether you store the result of calling `g.GetList()` into a variable or not won't make a difference one way or another. If you add the if-statements in that last block then obviously *that's* different code. – Lasse V. Karlsen Nov 15 '17 at 20:19