Jas*_*dez 10 c# linq deferred-execution
我有一个接受Enumerable的函数.我需要确保对枚举数进行评估,但是如果它在List或其他"冻结"集合中已经准备就绪,我宁愿不创建它的副本(例如,通过ToList()或ToArray()).冻结我指的是已经建立了一组项目的集合,例如List,Array,FsharpSet,Collection等,而不是像Select()和where()这样的linq.
是否有可能创建一个函数"ForceEvaluation",可以确定枚举是否已将执行挂起,然后评估可枚举?
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()}
}
Run Code Online (Sandbox Code Playgroud)
}
经过一些研究后,我意识到这在任何实际意义上都是不可能的,并且需要对每个迭代器进行复杂的代码检查.
所以我将使用Mark的答案的变体并创建一个已知安全类型的白名单,并且只需调用ToList()不在白名单上的任何内容.
感谢大家的帮助.
编辑*经过更多的反思,我意识到这相当于停止问题.所以非常不可能.
小智 6
对我有用的东西:
IEnumerable<t> deffered = someArray.Where(somecondition);
if (deffered.GetType().UnderlyingSystemType.Namespace.Equals("System.Linq"))
{
//this is a deffered executin IEnumerable
}
Run Code Online (Sandbox Code Playgroud)
你可以尝试一个充满希望的对证IList<T>或ICollection<T>,但要注意的是,这些能仍然可以懒洋洋地实现-但它是非常罕见,和LINQ没有做到这一点-它只是使用迭代器(不懒惰集合).所以:
var list = foos as IList<Foo>;
if(list != null) return list; // unchanged
return foos.ToList();
Run Code Online (Sandbox Code Playgroud)
请注意,这与常规.ToList()不同,每次都会返回不同的列表,以确保不会发生任何意外情况.
大多数具体的集合类型(包括T[]和List<T>)都满足IList<T>.我不熟悉F#集合 - 您需要检查它.