-5

I'm in a situation where it would be really nice to be able to determine what boolean expression I use for the terminating statement of a for loop at runtime. Or in more simpler words, decide whether I want i > 0, or i < file.length and decrement or increment i respectively. I know you can use lambdas to make the iterator either decrement or increment at runtime, explained in this SO question, but is something along the same lines possible for the terminator?

From trying to attempt this myself with System.Action to act as an anonymous function so I can still access the objects the for loop uses whilst inside action having some logic to determine whether or not I go forwards or backwards (this ended up with me realising that this wont work), it seems as if this is very much so the case of, if it is possible, it's far more complicated and is not worth the boilerplate code required compared to just having two loops within an if/else statement. I can't be the only one that has wondered this, surely!

EDIT: For those who do not understand what I'm asking, focus on the first paragraph, the second just describes my efforts. itsme86's answer describes pretty succinctly what I wondered was possible, providing it runs of course.

Community
  • 1
  • 1
Bradley
  • 1,234
  • 1
  • 12
  • 24
  • 1
    The real question is why. Why would you want to do something so obtuse and sensitive to change? – David L Jul 18 '16 at 15:08
  • What about a function that would return two objects, a boolean and an index ? – Dese Jul 18 '16 at 15:08
  • @David L I quickly asked myself the same question, but the competitive spirit in me tried and failed, and now I want to see if it's simply possible! – Bradley Jul 18 '16 at 15:08
  • 1
    Can you at least post a pseudo-code example of what you _want_ to do. Certainly you can replace the constant expressions in a for-loop with variables, but it's unclear exactly how you want to define it. – D Stanley Jul 18 '16 at 15:09
  • For the simple examples you give you could just use an `IEnumerable` and a `foreach` loop instead. – Ian Mercer Jul 18 '16 at 15:10
  • Note: This question is not a case of why, I simply want to know if it's possible to dynamically decide what boolean expression you use in a for loop based upon some condition you pre-determine. I guess this would be easy if you could store boolean expressions in variables? – Bradley Jul 18 '16 at 15:12
  • 1
    You're trying to access locals from an outside context -- that's never possible. One approach I could imagine is by hoisting all the locals out to a state machine that groups all that information in a class. That's nasty though. If you have both the caller and the `for` in the same scope (e.g. local) then you could just provide a `Func` for the condition of course, just like the lambdas as mentioned earlier. – Jeroen Vannevel Jul 18 '16 at 15:15
  • @JeroenVannevel This is what I was initially brainstorming, providing a Func and it being really nice and elegant, unfortunately it's not the case :( – Bradley Jul 18 '16 at 15:20
  • 3
    @Bradley - yes it's possible - yes you can store boolean expressions in variables. Your last comment says that it's not "nice and elegant" but you haven't actually _shown_ anything! Without something specific that indicates better what you're looking for (or what you have tried that is not "nice and elegant") I'm afraid this question is too broad. – D Stanley Jul 18 '16 at 15:25
  • @Bradley No responses to the answers that have been posted for quite some time. If those don't do what you're looking for, maybe you could explain how/why. – itsme86 Jul 18 '16 at 15:27
  • My apologies, I missread @JeroenVannevel by thinking he confirmed that using Func isn't possible, which is why I agreed that it wasn't the case whilst stating that, in my head at least, it would be nice and elegant compared to an if/else with two loops for each boolean expression. I should mention I'm at work so I'm heavily distracted, again apologies. I'm only here to learn :) – Bradley Jul 18 '16 at 15:43

2 Answers2

1

You can replace the condition in a loop with a delegate. Something like this works:

int i = 0;
Func<bool> predicate = () => i < 5;
for (; predicate(); ++i)
     Console.WriteLine(i);

Just assign a different delegate to predicate if you want a different condition.

EDIT: This might be a clearer example:

Func<int, bool> countToFive = num => num < 5;
Func<int, bool> countToTen = num => num < 10;

var predicate = countToFive;

for (int i = 0; predicate(i); ++i)
    Console.WriteLine(i);
itsme86
  • 19,266
  • 4
  • 41
  • 57
0

For the examples you give you can use an IEnumerable and foreach:

IEnumerable<int> forward = Enumerable.Range(0, file.Length);
IEnumerable<int> backward = Enumerable.Range(0, file.Length)
                               .Select(i => file.Length - i);

var sequence = forward; // or backward

foreach (int i in sequence) { ... }
Ian Mercer
  • 38,490
  • 8
  • 97
  • 133