Near "Ideal World" Solution
The following is valid C#
public static void Main()
{
var i = 0;
string value;
while ((value = GetValue(i++)) != null)
{
DoSomethingWith(value);
}
}
private static string GetValue(int input)
{
if (input > 20)
{
return null;
}
return input.ToString();
}
private static void DoSomethingWith(string value)
{
Console.WriteLine(value);
}
Compare with your "Ideal world scenario":
var i = 0;
while((var value = GetValue(i++)) != null)
{
DoSomethingWith(value);
}
All I had to do was to pull value
outside the loop. You seem willing to do this for all the presented alternatives. Thus, I don't think this is too much of a stretch.
"Infinite" While alternative
I have been playing around with the alternatives... here is another one:
var i = 0;
while (true)
{
var value = GetValue(i++);
if (value == null)
{
break;
}
DoSomethingWith(value);
}
In this case you can declare value
inside the loop (and using var
), you don't need to check for null
twice, you don't need to call GetValue
twice with the same input, and you don't have to create a wrapper with an out
parameter.
Alternative using For
We may try to express the same thing using a for
loop. Although, the naive approach does not work:
// I repeat, this does not work:
var i = 0;
for (string value = null; value != null; value = GetValue(i++))
{
DoSomethingWith(value);
}
The problem with this version is that it starts with value
being null
, which meets the exit criterion, and thus you get no iterations.
As JimmyJames points out you can write it like this:
var i = 0;
for(string value; (value = GetValue(i++)) != null;)
{
DoSomethingWith(value);
}
The only drawback I see is that you need to write the type (you can't use var
).
Addendum: This is another variant suggested by Maliafo:
var i = 0;
for (var value = GetValue(i); value != null; value = GetValue(++i))
{
DoSomethingWith(value);
}
While this version requires to write GetValue
, it doens't call it twice with the same value.
Do you want to declare i
in the scope too? Have a look at this:
for (var i = 0; ; i++)
{
var value = GetValue(i);
if (value == null)
{
break;
}
DoSomethingWith(value);
}
This is the same loop that we see in the "infinite" while solution I posted above. Yet, since I had no condition on the while... why not use change it to a for
to increment i
?
Addendum: Also see NetMage's answer for an interesting use of C# 7.0 features.
value
outside the loop.for(var value; (value = GetValue(i++)) != null;)