我有这个迭代器并希望它在某些条件下停止,因此,有一个名为“condition”的第三个参数。
public static IEnumerable<long> Dates(long start, int step, bool condition)
{
var k = start + step;
while (condition)
{
k += step;
yield return k;
}
}
我这样称呼它:
var i = 0;
foreach (var k in Iterator.Dates(0, 5, i++ < 100))
{
// Here goes infinite loop because (i++ < 100) is always true inside iterator
}
不幸的是,这个参数在内部循环中没有改变,所以现在总是如此,因为它似乎只在第一次迭代时执行。
问题:如何在每次迭代中检查或执行“条件”?
答案 0 :(得分:8)
参数是bool,但你需要这样的谓词函数:
public static IEnumerable<long> Dates(long start, int step, Func<bool> condition)
{
var k = start + step;
while (condition())
{
k += step;
yield return k;
}
}
用法:
var i = 0;
foreach (var k in Dates(0, 5, () => i++ < 100))
{
// Here goes infinite loop because (i++ < 100) is always true inside iterator
}
<强>评论强>
() => i++ < 100
是lambda表达式,类似于布尔函数,不含参数,返回i++ < 100
。
答案 1 :(得分:2)
您想要提供的是一项功能,规则。相反,你提供了一个值,并且在调用方法之前在表达式中计算了这个值,因此在方法中它是常量,永远不会改变,就像你观察到的那样。
相反,你需要传递一个代表,你&#34;委托&#34;向调用者提供规则的责任。
适用于此示例的简单委托类型是Func<T>
,其基本上定义如下:
public delegate T Func<T>();
这是一个委托,它包装一个返回值的方法,而不需要任何参数。
由于您希望在while
语句中使用此函数的结果,因此需要它返回bool
。
以下是您如何申报该方法:
public static IEnumerable<long> Dates(long start, int step, Func<bool> condition)
{
var k = start + step;
while (condition())
{
k += step;
yield return k;
}
}
请注意,您需要将while
表达式更改为调用委托。因为它包装了一个方法,所以要从方法中获取值,你必须调用它。
以下是如何调用新方法:
var i = 0;
foreach (var k in Iterator.Dates(0, 5, () => i++ < 100))
{
// No longer infinite loop because (i++ < 100) is now evaluated on every iteration
}
这个新表达:
() => i++ < 100
与写这个基本相同:
int i;
bool Func()
{
return i++ < 100;
}
但是用较小的语法包装。
现在,每次循环运行一次迭代时,它将调用此func,这将增加该值并将其与100进行比较。