List<T>.RemoveAll() efficiency / compiler optimisation
The answer is no it doesn't optimize out the allocation of the array
Basically, every time the predicate is called, it checks against the compiler generated class and initializes a new array to call the Contains
(as you can see here)
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static Predicate<int> <>9__0_0;
internal bool <M>b__0_0(int i)
{
// bam!
int[] obj = new int[3];
RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
return Enumerable.Contains(obj, i);
}
}
As @Michael Randall already wrote, it looks like it is not possible.
I agree, that your questioned code is nicely readable, having the list in the RemoveAll method. But to have the instance only once, I have three ideas of doing it:
int[] a = null;
foo.RemoveAll(i => (a ?? (a = new[] { 1, 3, 5 })).Contains(i));
This is actually yours, with little un-beatuness of needing an external variable.
foo = foo.Except(new[] { 1, 3, 5 }).ToList();
That's actually pretty nice solution using Linq.
new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));
new[] {1, 3, 5}.Iterate(x => foo.Remove(x));
This is something I'd do. In neary all of my code I have my Extension method "Iterate" to avoid the need of foreach. And also, i dont want to "toList" everything all the time to make a .ForEach(..)
static class Extensions
{
public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
{
foreach (var item in source)
{
action.Invoke(item);
}
}
}