自定义迭代器的实现不会更改其参数之一
Implementation of custom iterator does not change one of its parameters
我有这个迭代器并希望它在某些情况下停止,因此,有一个名为 "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
}
不幸的是,此参数不会在循环内更改,所以现在它始终为真,因为它似乎只在第一次迭代时执行。
问题:如何在每次迭代时检查或执行"condition"?
参数是 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 表达式 没有参数 即 returns i++ < 100
.
您想要提供的是一项功能,一个规则。相反,你提供了一个 value,这个值是在调用方法之前在表达式中计算的,因此在方法内部它是常量,永远不会改变,就像你观察到的那样。
相反,您需要传递一个委托,您 "delegate" 有责任向调用者提供规则。
适合此示例的简单委托类型是 Func<T>
,其基本定义如下:
public delegate T Func<T>();
这是一个委托,它包装了一个 return 是一个值的方法,不带任何参数。
由于要在 while
语句中使用此函数的结果,因此需要它 return 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;
}
但包含在更小的语法中。
现在,循环每运行一次迭代,它就会调用这个函数,它会增加值并将其与 100 进行比较。
我有这个迭代器并希望它在某些情况下停止,因此,有一个名为 "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
}
不幸的是,此参数不会在循环内更改,所以现在它始终为真,因为它似乎只在第一次迭代时执行。
问题:如何在每次迭代时检查或执行"condition"?
参数是 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 表达式 没有参数 即 returns i++ < 100
.
您想要提供的是一项功能,一个规则。相反,你提供了一个 value,这个值是在调用方法之前在表达式中计算的,因此在方法内部它是常量,永远不会改变,就像你观察到的那样。
相反,您需要传递一个委托,您 "delegate" 有责任向调用者提供规则。
适合此示例的简单委托类型是 Func<T>
,其基本定义如下:
public delegate T Func<T>();
这是一个委托,它包装了一个 return 是一个值的方法,不带任何参数。
由于要在 while
语句中使用此函数的结果,因此需要它 return 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;
}
但包含在更小的语法中。
现在,循环每运行一次迭代,它就会调用这个函数,它会增加值并将其与 100 进行比较。