我是否可以知道IEnumerable
(或IQueryable
)的延迟评估是否已经发生?也就是说,是否曾调用GetEnumerator().MoveNext()
。有办法吗?
如何在以下示例中对HasBeenEvaluated()
进行编码?
private void Example()
{
IEnumerable<Thing> things = _Repository.GetObjects<Thing>();
bool x = HasBeenEvaluated(things); // returns false
foreach (var thing in things)
{
x = HasBeenEvaluated(things); // returns true
}
}
答案 0 :(得分:1)
一般来说,没有。接口IEnumerable<>
不支持。
另外,如果你有一个IEnumerator<>
,你通常无法判断是否曾调用MoveNext()
。
有时IEnumerator<>
会支持Reset()
方法,但这不是您要求的。当您尝试Reset()
时,许多枚举器只会抛出异常。
答案 1 :(得分:1)
您可以为IEnumerable
创建一个包装器,在迭代时,翻转一个布尔值以指示它已被迭代:
//TODO come up with a better name
public class Foo<T> : IEnumerable<T>
{
private IEnumerable<T> wrapped;
public Foo(IEnumerable<T> wrapped)
{
this.wrapped = wrapped;
}
public bool HasBeenIterated { get; private set; }
public IEnumerator<T> GetEnumerator()
{
HasBeenIterated = true;
foreach (var item in wrapped)
yield return item;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
您的方法现在可以成为:
private void Example()
{
var things = new Foo<Thing>(_Repository.GetObjects<Thing>());
bool x = things.HasBeenIterated;//is false
foreach (var thing in things)
{
x = things.HasBeenIterated;//is true
}
}
答案 2 :(得分:0)
也许您可以从类型继承并向其添加方法以返回状态。
在这种情况下,您将向此类添加一个属性,该属性将反映正在调用的操作的状态。
public class StatefulThings : IEnumerable<Thing>
{
bool _moveNextExecuted = false;
public override bool MoveNext()
{
// Perform next pointer
// Set state of hasBeenEnumerated in here...
_moveNextExecuted = true;
}
}