厳密に言えば、あなたが言っていることを正確に実行したいのであれば、そうです、GetEnumeratorを呼び出し、whileループで列挙子を自分で制御する必要があります。
ビジネス要件についてあまり知らなくても、次のようなイテレータ関数を利用できる場合があります。
public static IEnumerable<decimal> IgnoreSmallValues(List<decimal> list)
{
decimal runningTotal = 0M;
foreach (decimal value in list)
{
// if the value is less than 1% of the running total, then ignore it
if (runningTotal == 0M || value >= 0.01M * runningTotal)
{
runningTotal += value;
yield return value;
}
}
}
次に、これを行うことができます:
List<decimal> payments = new List<decimal>() {
123.45M,
234.56M,
.01M,
345.67M,
1.23M,
456.78M
};
foreach (decimal largePayment in IgnoreSmallValues(payments))
{
// handle the large payments so that I can divert all the small payments to my own bank account. Mwahaha!
}
更新しました:
さて、これが私の「釣り針」ソリューションと呼んでいるもののフォローアップです。さて、私がこのように何かをする正当な理由を本当に考えることができないという免責事項を追加させてください、しかしあなたの状況は異なるかもしれません。
アイデアは、イテレータ関数に渡す「釣り針」オブジェクト(参照型)を作成するだけです。イテレータ関数は釣り針オブジェクトを操作します。外部のコードにはまだそれへの参照があるため、何が起こっているのかを可視化できます。
public class FishingHook
{
public int Index { get; set; }
public decimal RunningTotal { get; set; }
public Func<decimal, bool> Criteria { get; set; }
}
public static IEnumerable<decimal> FishingHookIteration(IEnumerable<decimal> list, FishingHook hook)
{
hook.Index = 0;
hook.RunningTotal = 0;
foreach(decimal value in list)
{
// the hook object may define a Criteria delegate that
// determines whether to skip the current value
if (hook.Criteria == null || hook.Criteria(value))
{
hook.RunningTotal += value;
yield return value;
hook.Index++;
}
}
}
あなたはそれをこのように利用するでしょう:
List<decimal> payments = new List<decimal>() {
123.45M,
.01M,
345.67M,
234.56M,
1.23M,
456.78M
};
FishingHook hook = new FishingHook();
decimal min = 0;
hook.Criteria = x => x > min; // exclude any values that are less than/equal to the defined minimum
foreach (decimal value in FishingHookIteration(payments, hook))
{
// update the minimum
if (value > min) min = value;
Console.WriteLine("Index: {0}, Value: {1}, Running Total: {2}", hook.Index, value, hook.RunningTotal);
}
// Resultint output is:
//Index: 0, Value: 123.45, Running Total: 123.45
//Index: 1, Value: 345.67, Running Total: 469.12
//Index: 2, Value: 456.78, Running Total: 925.90
// we've skipped the values .01, 234.56, and 1.23
基本的に、FishingHookオブジェクトを使用すると、イテレータの実行方法をある程度制御できます。質問から得た印象は、イテレータの内部動作にアクセスして、イテレータの途中でイテレータがどのように反復するかを操作できるようにする必要があるということでしたが、そうでない場合は、このソリューションが必要なものをやり過ぎてください。