gpt4 book ai didi

c# - 在 foreach 循环中访问 Enumerator?

转载 作者:行者123 更新时间:2023-12-04 13:05:03 30 4
gpt4 key购买 nike

我有一个 List 类,我想覆盖 GetEnumerator() 以返回我自己的 Enumerator 类。此 Enumerator 类将具有两个附加属性,这些属性将在使用 Enumerator 时更新。

为简单起见(这不是确切的业务案例),假设这些属性是 CurrentIndexRunningTotal

我可以在 foreach 循环中手动管理这些属性,但我宁愿封装此功能以供重用,而 Enumerator 似乎是正确的位置。

问题: foreach 隐藏了所有枚举器业务,那么有没有办法在 foreach 语句中访问当前枚举器以便检索我的属性?还是我必须 foreach,使用讨厌的旧 while 循环,并自己操作枚举器?

最佳答案

严格来说,我会说,如果您想完全按照您所说的去做,那么是的,您需要调用 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 对象使您可以对迭代器的执行方式进行一些控制。我从这个问题中得到的印象是,你需要一些方法来访问迭代器的内部工作,这样你就可以在迭代过程中操纵它的迭代方式,但如果不是这种情况,那么这个解决方案可能为你所需要的而矫枉过正。

关于c# - 在 foreach 循环中访问 Enumerator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1828881/

30 4 0