Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在foreach循环中访问枚举器?_C#_Foreach_Ienumerator - Fatal编程技术网

C# 在foreach循环中访问枚举器?

C# 在foreach循环中访问枚举器?,c#,foreach,ienumerator,C#,Foreach,Ienumerator,我有一个List类,我想重写GetEnumerator()以返回我自己的枚举器类。此枚举器类将具有两个附加属性,这些属性将在使用枚举器时更新 为简单起见(这不是确切的业务案例),假设这些属性是CurrentIndex和RunningTotal 我可以在foreach循环中手动管理这些属性,但我更愿意封装此功能以供重用,而枚举器似乎是正确的位置 问题:foreach隐藏了所有枚举器业务,那么是否有办法在foreach语句中访问当前枚举器,以便检索我的属性?或者我必须使用foreach,使用一个讨厌

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

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

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


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

使用
foreach
你确实无法获得枚举数-但是,你可以让枚举数返回(
yield
)一个包含该数据的元组;事实上,你可以用LINQ来帮你做

(我无法使用LINQ干净地获取索引-但是可以通过
聚合
获取总值和当前值;所以这里是元组方法)

使用系统集合;
使用System.Collections.Generic;
使用制度;
类MyTuple
{
公共int值{get;private set;}
公共int索引{get;private set;}
public int RunningTotal{get;private set;}
公共MyTuple(int值、int索引、int runningTotal)
{
值=值;索引=索引;RunningTotal=RunningTotal;
}
静态IEnumerable方法(IEnumerable数据)
{
整数指数=0,总计=0;
foreach(数据中的int值)
{
返回新的MyTuple(值,索引+++,
总数=总数+价值);
}
}
静态void Main()
{
int[]数据={1,2,3};
foreach(SomeMethod(数据)中的变量元组)
{
Console.WriteLine(“{0}:{1};{2}”),tuple.Index,
tuple.Value,tuple.RunningTotal);
}
}
}

严格地说,我想说,如果你想完全按照你说的去做,那么是的,你需要调用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,
            .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
var ZippedSequence = ValueList.Zip(Indexes, (value, index) => new {value, index}).Zip(RunningTotals, (temp, total) => new {temp.value, temp.index, total});
public静态IEnumerable IgnoreSmallValues(列表)
{
十进制运行总计=0M;
foreach(列表中的十进制值)
{
//如果该值小于运行总数的1%,则忽略它
如果(运行总计==0M | |值>=0.01M*运行总计)
{
runningTotal+=值;
收益回报值;
}
}
}
然后你可以这样做:

        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!
        }
列表付款=新列表(){
123.45米,
234.56米,
.01米,
345.67米,
1.23米,
456.78米
};
foreach(十进制大额付款,金额较小(付款))
{
//处理大额付款,这样我就可以把所有小额付款转移到我自己的银行账户上!
}

更新: 好的,下面是我所谓的“钓鱼钩”解决方案的后续内容。现在,让我添加一个免责声明,我真的想不出这样做的好理由,但您的情况可能会有所不同

其思想是,您只需创建一个传递给迭代器函数的“钓鱼钩”对象(引用类型)。迭代器函数操纵您的钓鱼钩对象,并且由于您在外部代码中仍然有对它的引用,因此您可以看到正在发生的事情:

    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++;
            }
        }
    }
public-class-FishingHook
{
公共int索引{get;set;}
公共十进制运行总数{get;set;}
公共函数条件{get;set;}
}
公共静态IEnumerable FishingHookiOperation(IEnumerable列表,FishingHook)
{
指数=0;
hook.RunningTotal=0;
foreach(列表中的十进制值)
{
//钩子对象可以定义一个条件委托
//确定是否跳过当前值
if(hook.Criteria==null | | hook.Criteria(value))
{
hook.RunningTotal+=值;
收益回报值;
hook.Index++;
}
}
}
您可以这样使用它:

    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,
            .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
var ZippedSequence = ValueList.Zip(Indexes, (value, index) => new {value, index}).Zip(RunningTotals, (temp, total) => new {temp.value, temp.index, total});
列表付款=新列表(){
123.45米,
.01米,
345.67米,
234.56米,
1.23米,
456.78米
};
FishingHook hook=新的FishingHook();
十进制最小值=0;
hook.Criteria=x=>x>min;//排除小于/等于定义的最小值的任何值
foreach(捕鱼作业(付款、钩)中的十进制值)
{
//更新最小值
如果(值>最小值)最小值=值;
WriteLine(“索引:{0},值:{1},运行总数:{2}”,hook.Index,值,hook.RunningTotal);
}
//结果输出为:
//索引:0,值:123.45,运行总数:123.45
//指数:1,数值:345.67,运行总数:469.12
//指数:2,数值:456.78,运行总数:925.90
//我们跳过了值.01、234.56和1.23

本质上,FishingHook对象为您提供了对迭代器执行方式的一些控制。我从这个问题中得到的印象是,你需要一些方法来访问迭代器的内部操作,这样你就可以在迭代过程中操纵它如何迭代,但是如果不是这样,那么这个解决方案可能对你所需要的东西来说是多余的。