I have a function that accepts an Enumerable. I need to ensure that the enumerator is evaluated, but I’d rather not create a copy of it (e.g. via ToList() or ToArray()) if it is all ready in a List or some other “frozen” collection. By Frozen I mean collections where the set of items is already established e.g. List, Array, FsharpSet, Collection etc, as opposed to linq stuff like Select() and where().
Is it possible to create a function “ForceEvaluation” that can determine if the enumerable has deffered execution pending, and then evaluate the enumerable?
public void Process(IEnumerable<Foo> foos)
{
IEnumerable<Foo> evalutedFoos = ForceEvaluation(foos)
EnterLockedMode(); // all the deferred processing needs to have been done before this line.
foreach (Foo foo in foos)
{
Bar(foo);
}
}
public IEnumerable ForceEvaluation(IEnumerable<Foo> foos)
{
if(??????)
{ return foos}
else
{return foos.ToList()}
}
}
After some more research I’ve realized that this is pretty much impossible in any practical sense, and would require complex code inspection of each iterator.
So I’m going to go with a variant of Mark’s answer and create a white-list of known safe types and just call ToList() anything not on that is not on the white-list.
Thank you all for your help.
Edit*
After even more reflection, I’ve realized that this is equivalent to the halting problem. So very impossible.
You could try a hopeful check against
IList<T>orICollection<T>, but note that these can still be implemented lazily – but it is much rarer, and LINQ doesn’t do that – it just uses iterators (not lazy collections). So:Note that this is different to the regular
.ToList(), which gives you back a different list each time, to ensure nothing unexpected happens.Most concrete collection types (including
T[]andList<T>) satisfyIList<T>. I’m not familiar with the F# collections – you’d need to check that.