c#---foreach循环研究及迭代器

foreach循环研究及迭代器

 

1.IEnumerable接口:

命名空间:System.CollectionsSystem.Collections 命名空间包含接口和类,这些接口和类定义各种对象(如列表、队列、位数组、哈希表和字典)的集合。)

IEnumerable 包含单一方法 GetEnumerator,该方法返回 IEnumerator

IEnumerator 提供了通过公开 Current 属性和 MoveNextReset 方法来循环访问集合的功能。

IEnumerable.GetEnumerator方法返回循环访问集合的枚举数,返回值为IEnumerator 对象。

最初,枚举数定位在集合中第一个元素的前面。 Reset 方法还将枚举器恢复到此位置。 在此位置,Current 属性是不确定的。 因此,在读取 Current的值之前,必须调用 MoveNext 方法将枚举器推进到集合的第一个元素。

 

2.foreach 循环的实现方式:

首先,使用foreach结构可以迭代一个数组,因为System.Array类实现了IEnumerable接口,这个接口的唯一方法GetEnumerator()可以迭代集合中的各项。

foreach循环迭代一个collectionObject集合的过程:

a,调用collectionObject.GetEnumerator(),返回一个IEnumerator引用,

b,调用所返回的IEnumerator接口的MoveNext()方法,

c,MoveNext返回true,就使用IEnumerator接口的Current属性来获取对象的一个引用,用于foreach循环,

d,重复前面两步,直到MoveNext()方法返回false为止,此时循环停止。

若需在类中进行这些操作,必须重写几个方法,跟踪索引,维护current属性,以及执行其他一些操作,一个较为简单的替代方法是使用迭代器。

 

3.迭代器

迭代器的定义是,它是一个代码块,按顺序提供了要在foreach块中使用的所有值。

一般情况下,这个代码块是一个方法,但也可以使用属性访问器和其他代码块作为迭代器。

 

无论代码块是什么,其返回类型都是有限的。而迭代器块的返回类型是前面提到的接口类型IEnumerable和Ienumerator。使用这两个类型的场合是:

a,如果要迭代一个类,可使用方法GetEnumerator(),其返回类型是IEnumerator。

b,如果要迭代一个类成员,例如方法,则使用IEnumerable。

在迭代器块中,使用yield关键字选择要在foreach循环中使用的值。

 

一个简单的迭代器(封装素数):

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Ch11Ex03
{
   public class Primes
    {
        private long min;
        private long max;
        public Primes() : this(2,100) { }
        public Primes(long minimum,long maximum)
        {
            if (minimum<2)
            {
                min = 2;
            }
            else
            {
                min = minimum;
            }
            max = maximum;
        }
        public IEnumerator GetEnumerator()
        {
            for (long possiblePrime = min; possiblePrime <=max; possiblePrime++)
            {
                bool isPrime = true;
                for (long possibleFactor = 2; possibleFactor <=(long)Math.Floor(Math.Sqrt(possibleFactor)); possibleFactor++)
                {
                    long remainderAfterDivision = possiblePrime % possibleFactor;
                    if (remainderAfterDivision==0)
                    {
                        isPrime = false;
                        break;
                    }
                }
                if (isPrime)
                {
                    yield return possiblePrime;
                }
            }
        }
    }
}

 

main函数执行:

 static void Main(string[] args)
        {
            Primes primesFrom2To1000 = new Primes(2,1000);
            foreach (long i in primesFrom2To1000)
            {
                Console.Write($"{i}");
            }
            Console.ReadKey();
            //Console.WriteLine("Hello World!");
        }

说明:此迭代器可以枚举上下限之间的素数集合。foreach循环执行in collention时,进入迭代器执行

collectionObject.GetEnumerator(),然后yield返回循环值。

如果把上下限设置为非常大的数,在程序执行时会发现,一次显示一个结果,中间有暂停,而不是一次显示所有结果。这说明,无论代码在yield调用之间是否终止,迭代器代码都会一次返回一个结果。如果在调试模式下运行代码,会发现调用yield会中断代码的执行,当请求一个值时,也就是使用迭代器的foreach循环开始一个新循环时,代码会恢复执行。

IEnumerator接口官方文档:https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.ienumerator?view=netframework-4.8

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值