W3bbo said:
exoteric said:
*snip*

Methods for working with lists to allow editing them within foreach loops without needing to manage a separate itemsToRemove list yourself:

 

Because C# 3.0 doesn't support generic covariance I couldn't avoid using the Object type in the dictionary.

 

 // how do you do a Dictionary<List<T>,List<T>> where T is unknown? the CLR doesn't support generic inheritance (So you can't do Dictionary<List<Object>,List<Object>> *AND* ensure Object == Object too) private static Dictionary<Object,Object>
 _pendingRemovals = new Dictionary<Object,Object>(); private static List<T> GetPendingRemovals<T>(IList<T> list) { if( !_pendingRemovals.ContainsKey( list ) ) _pendingRemovals.Add( list, new List<T>() ); List<T> pendingRemovals = (List<T>)_pendingRemovals[
 list ]; return pendingRemovals; } /// <summary>Removes <paramref name="removeThis"/> from the list when RemoveCommit is called.</summary> public static void RemovePending<T>(this IList<T> list, T removethis) { List<T> pendingRemovals = GetPendingRemovals(
 list ); pendingRemovals.Add( removethis ); } /// <summary>Removes all pending items from the list</summary> public static void RemoveCommit<T>(this IList<T> list) { List<T> pendingRemovals = GetPendingRemovals( list ); foreach(T item in pendingRemovals) {
 list.Remove( item ); } _pendingRemovals.Remove( list ); } /// <summary>Cancels all pending item removals from <param name="list" /></summary> public static void RemoveCancel<T>(this IList<T> list) { _pendingRemovals.Remove( list ); } /// <summary>Cancels a
 particular pending removal.</summary> public static void RemoveCancel<T>(this IList<T> list, T dontRemoveThis) { List<T> pendingRemovals = GetPendingRemovals( list ); pendingRemovals.Remove( dontRemoveThis ); }

 

Usage:

List<Bar> bar = GetBarList(); foreach(Foo foo in bar) { if( foo.NeedsDeleting ) bar.PendingRemove( foo ); } bar.PendingCommit();

That's pretty cool.  I prefer a different approach, however.

 

public static void RemoveWhere<T>(this IList<T> list, Func<T, bool> where) { for (int i = 0; i < list.Count; i++) if (where(list[i])) list.RemoveAt(i--); } //... var list = new List<string> { "Jon", "Bob", "Joe", "Herb", "Billy",
 "Boe" }; list.RemoveWhere(s => s.StartsWith("B")); // results in { "Jon", "Joe", "Herb" }

 

EDIT: Haha, and apparently the library designers agree.  List<T> already defines a RemoveAll method that does the same thing.  To be fair though, this works on any IList<T>.