我如何判断 IEnumerable 是否已被评估?
How can I tell if an IEnumerable has been evaluated?
我能知道 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
}
}
一般来说,不会。接口 IEnumerable<>
不支持。
此外,如果您有一个 IEnumerator<>
,您通常无法判断是否曾经调用过 MoveNext()
。
有时 IEnumerator<>
会支持 Reset()
方法,但这不是您所要求的。当您尝试 Reset()
.
时,许多枚举器只会抛出异常
也许您可以从该类型继承并向其添加方法以 return 状态。
在这种情况下,您可以向此 class 添加一个 属性,以反映正在调用的操作的状态。
public class StatefulThings : IEnumerable<Thing>
{
bool _moveNextExecuted = false;
public override bool MoveNext()
{
// Perform next pointer
// Set state of hasBeenEnumerated in here...
_moveNextExecuted = true;
}
}
您可以为 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
}
}
我能知道 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
}
}
一般来说,不会。接口 IEnumerable<>
不支持。
此外,如果您有一个 IEnumerator<>
,您通常无法判断是否曾经调用过 MoveNext()
。
有时 IEnumerator<>
会支持 Reset()
方法,但这不是您所要求的。当您尝试 Reset()
.
也许您可以从该类型继承并向其添加方法以 return 状态。
在这种情况下,您可以向此 class 添加一个 属性,以反映正在调用的操作的状态。
public class StatefulThings : IEnumerable<Thing>
{
bool _moveNextExecuted = false;
public override bool MoveNext()
{
// Perform next pointer
// Set state of hasBeenEnumerated in here...
_moveNextExecuted = true;
}
}
您可以为 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
}
}