6

I implemented an ExtensionMethod which basically works as ForEach-Loop, my Implementation looks like this:

public static void ForEach(this ListItemCollection collection, Action<ListItem> act )
{
    foreach (ListItem item in collection)
        act(item);
}

However, I'd like the method to stop looping after the first time a specific condition is met.

Here's how I currently use it:

ddlProcesses.Items.ForEach(item => item.Selected = item.Value == Request["Process"]?true:false);

The Problem with this is that there can only be one item inside the DropDownList which matches this requirement, but the loop is being finished anyway, what would be the least ugly way to solve this problem?

Thanks.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Dennis Röttger
  • 1,975
  • 6
  • 32
  • 51

4 Answers4

5

You can take a Func<ListItem, bool> instead of an Action<ListItem> and break the loop if it returns true:

public static void ForEach(this ListItemCollection collection,
    Func<ListItem, bool> func)
{
    foreach (ListItem item in collection) {
        if (func(item)) {
            break;
        }
    }
}

You can use it like this:

ddlProcesses.Items.ForEach(
    item => item.Selected = (item.Value == Request["Process"]));
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
2
public static void ForEach(this ListItemCollection collection, Action<ListItem> act )
{
    foreach (ListItem item in collection)
    {
        act(item);
        if(condition) break;
    }
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Gabriel
  • 1,435
  • 3
  • 17
  • 24
1

First do this:

IEnumerable<ListItem> e = ddlProcesses.Items.OfType<ListItem>(); // or Cast<ListItem>()

to get generic collection.

Then use can roll your own, generic extension method:

public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
    foreach (T item in collection) action(item);
}

public static void ForEach<T>(this IEnumerable<T> collection, Func<T> func)
{
    foreach (T item in collection) if (func(item)) return;
}

Anyway, cache lookup result:

var process = Request["Process"];

e.ForEach(i => i.Selected = i.Value == process);
Community
  • 1
  • 1
abatishchev
  • 98,240
  • 88
  • 296
  • 433
1

Your requirements are not 100% clear. Do you need to process all items to set them to false except the only one which matches the condition or do you just want to find the with the right condition or do you want to apply a function until a condition is met?

  1. Only do something to an item the first time the condition matches

    public static void ApplyFirst(this ListItemCollection collection,
                          Action<ListItem> action, Func<ListItem, bool> predicate)
    {
        foreach (ListItem item in collection) 
        {
           if (predicate(item))
           {
               action(item);
               return;
           }
        }
    }
    
  2. Do something to an item everytime a condition matches

    public static void ApplyIf(this ListItemCollection collection,
                          Action<ListItem> action, Func<ListItem, bool> predicate)
    {
        foreach (ListItem item in collection) 
        {
           if (predicate(item))
           {
               action(item);
           }
        }
    }
    
  3. Do something to all items until a condition matches

    public static void ApplyUntil(this ListItemCollection collection,
                          Action<ListItem> action, Func<ListItem, bool> predicate)
    {
        foreach (ListItem item in collection) 
        {
           action(item);
           if (predicate(item))
           {
               return;
           }
        }
    }
    
ChrisWue
  • 18,612
  • 4
  • 58
  • 83