In wondering the differences between for, foreach, while, and goto a few weeks ago so I wrote up this test code. All of the methods will compile into the same IL (other then a variable name on the foreach version.) In debug mode a few NOP statements will be in different positions.
static void @for<T>(IEnumerable<T> input)
{
T item;
using (var e = input.GetEnumerator())
for (; e.MoveNext(); )
{
item = e.Current;
Console.WriteLine(item);
}
}
static void @foreach<T>(IEnumerable<T> input)
{
foreach (var item in input)
Console.WriteLine(item);
}
static void @while<T>(IEnumerable<T> input)
{
T item;
using (var e = input.GetEnumerator())
while (e.MoveNext())
{
item = e.Current;
Console.WriteLine(item);
}
}
static void @goto<T>(IEnumerable<T> input)
{
T item;
using (var e = input.GetEnumerator())
{
goto check;
top:
item = e.Current;
Console.WriteLine(item);
check:
if (e.MoveNext())
goto top;
}
}
static void @gotoTry<T>(IEnumerable<T> input)
{
T item;
var e = input.GetEnumerator();
try
{
goto check;
top:
item = e.Current;
Console.WriteLine(item);
check:
if (e.MoveNext())
goto top;
}
finally
{
if (e != null)
e.Dispose();
}
}
Per @Eric's comment...
I have expanded for
, while
, 'goto' and foreach
with generic arrays. Now the for each
statement looks to use the indexer for the array. Object arrays and strings are expanded in similar ways. Objects will remove a boxing that occurs before the method call to Console.WriteLine and Strings will replace T item
and T[] copy...
with char item
and string copy...
respectively. Note that the critical section is no longer need because the disposable enumerator is no longer used.
static void @for<T>(T[] input)
{
T item;
T[] copy = input;
for (int i = 0; i < copy.Length; i++)
{
item = copy[i];
Console.WriteLine(item);
}
}
static void @foreach<T>(T[] input)
{
foreach (var item in input)
Console.WriteLine(item);
}
static void @while<T>(T[] input)
{
T item;
T[] copy = input;
int i = 0;
while (i < copy.Length)
{
item = copy[i];
Console.WriteLine(item);
i++;
}
}
static void @goto<T>(T[] input)
{
T item;
T[] copy = input;
int i = 0;
goto check;
top:
item = copy[i];
Console.WriteLine(item);
i++;
check:
if (i < copy.Length)
goto top;
}