如果我正确理解了您的问题,那么不,一旦启动查询,就没有(内置)方法可以“停止”查询。如果您想在枚举期间添加相当于取消谓词的内容,这表明枚举是否应该继续,最简单的方法是创建自定义迭代器。这样的实现可能如下所示:
public sealed class BreakingEnumerable<T> : IEnumerable<T>
{
private readonly IEnumerable<T> _query;
private readonly Predicate<T> _continuePredicate;
public BreakingEnumerable(IEnumerable<T> query, Predicate<T> predicate)
{
_query = query ?? throw new ArgumentNullException(nameof(query));
_continuePredicate = predicate ?? throw new ArgumentNullException(nameof(predicate));
}
public IEnumerator<T> GetEnumerator()
{
foreach (var item in _query)
{
if (_continuePredicate(item))
{
yield return item;
}
else
{
yield break;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
当然,您希望将这部分作为查询的一部分,因此您可能需要一个扩展方法类来将查询转换为这个自定义枚举:
public static class BreakingEnumerableExtensions {
public static BreakingEnumerable<T> WithTerminationClause<T>(
this IEnumerable<T> query,
Predicate<T> breakCondition)
{
return new BreakingEnumerable<T>(query, breakCondition);
}
}
这是实际用法:
static void Main(string[] args)
{
var enumerable = Enumerable.Range(1, 100);
var array = enumerable.WithTerminationClause(i => i > 100).ToArray();
Console.WriteLine($"Enumerable with termination clause array length: {array.Length}");
array = enumerable.Where(i => i < 20).WithTerminationClause(i => i % 2 == 0)
.ToArray();
Console.WriteLine($"Enumerable with termination clause length: {array.Length}");
}
产生结果:
Enumerable with termination clause array length: 0
Enumerable with termination clause length: 9
这可以链接起来产生一些小的优化:
// Outputs: `Query results: [100, 200, 300]`
var enumerable = Enumerable.Range(1, 100);
var sub = enumerable.WithTerminationClause(i => i <= 3)
.Select(i => i * 100);
Console.WriteLine("Query results: [{0}]", string.Join(", ", sub));
唯一的“障碍”是你永远不会想要使用它,除非你可以保证某种形式的排序:例如,所有数字都以有序的顺序出现。如果您没有强制执行此保证,那么您的程序可能会产生不正确的结果。
希望这可以帮助!