I’m currently trying to write an extension method, but it doesn’t seem to be operating as intended. Before we delve too much deeper, here’s the code I have:
public static void Remove<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
var items = source.Where(predicate);
source = source.Where(t => !items.Contains(t));
}
The desire is that I can call this extension method on any IEnumerable and all items matching the predicate are then removed from the collection. I’m tired of iterating through collections to find the items that match and then removing them one at a time to avoid altering the collection while enumerating through it…
Anyway… When I step through the code, everything seems to work. Before existing the method, the source has the correct number of items removed. However, when I return to the calling code all of the items still exist in my original IEnumerable object. Any tips?
Thanks in advance,
Sonny
Can’t do that the way you have originally written it, you are taking a reference variable (
source) and making it refer to a new instance. This modifies the local referencesourceand not the original argument passed in.Keep in mind for reference types in C#, the default parameter passing scheme is pass by value (where the value being passed is a reference).
Let’s say you pass in a variable
xto this method, which refers to the original list and that list lives at theoretical location 1000, this means that source is a new reference to the original list living at location 1000.Now when you say:
You are assigning
sourceto a new list (say at location 2000), but that only affects whatsourcepoints to and not thexyou passed in.To fix this as an extension method, you would really want to
returnthe new sequence instead:This is all assuming you want to keep it totally generic to
IEnumerable<T>as you asked in your question. Obviously as also pointed out in other examples if you only care aboutList<T>there is a baked-inRemoveAll()method.