zoukankan      html  css  js  c++  java
  • C#编程(三十五)----------foreach和yield

    枚举

    foreach语句中使用枚举,可以迭代集合中的元素,且无需知道集合中的元素个数.

    数组或集合实现带GetEumerator()方法的IEumerable接口.GetEumerator()方法返回一个实现IEunmerable接口的枚举.

    GetEnumerator()方法用IEnumerable接口定义.foreach语句并不真的需要在集合类中实现这个借口.有一个名为GetEnumerator()的方法,他返回实现了IEnumerator接口的对象就足够了.

    IEnumerator接口

    foreach语句使用IEnumerator接口的方法和属性,迭代集合中的所有元素.为此IEnumerator定义了Current属性,来返回光标所在的元素,该接口的MoveNext()方法移动到集合的下一个元素上,如果有这个元素,该方法就返回true.如果集合不再有更多的元素,该方法就返回false.

    这个借口的泛型版本IEnumerator<T>派生自接口IDisposable,因此定义了Dispose()方法,来清理枚举器占用的资源.

    foreach语句

    C#foreach语句不会解释为IL代码中的foreach语句.C#编译器会把foreach语句转换为IEnumerable接口的方法和属性.案例:

    int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8 };

    foreach (var item in arr)

    {

         Console.WriteLine(item);

    }

    很明显,foreach语句很简洁,但是他的有点不仅仅在于此,它的效率也是很高的,不用考虑数组是几维的.案例:

    int[,] array = new int[8, 8];

                for (int i = 0; i < array.GetLength(0); i++)

                {

                    for (int j = 0; j < array.GetLength(1); j++)

                    {

    Console.WriteLine(array[i,j].ToString());

                    }

                }

                Console.ReadKey();

    使用foreach:

    foreach (int item in array)

                {

                    Console.WriteLine(item.ToString());

                }

    对于三维或者更多维,foreach语句不用发生任何变化,而对于for语句就要进行修改了.

    foreach完成类型转换操作,案例:

    int[] array = new int[100];

                ArrayList aList = new ArrayList();

                aList.AddRange(array);

                foreach (int item in aList)

                {

                    Console.WriteLine(item.ToString());

                }

                for (int i = 0; i < aList.Count; i++)

                {

                    int n = (int)aList[i];

                    Console.WriteLine(n.ToString());

                }

                Console.ReadKey();

    foreach并没有增加资源使用,由于对于继承了IEnumerable接口的数据类型,才能使用foreach语句,那么对于使用foreach会访问IEnumerable接口中的GetEnumerator()方法来进行枚举,那么对应如上的foreach语句,对应的语句如下:

    IEnumerator it = aList.GetEnumerator() as IEnumerator;

                using (IDisposable disp = it as IDisposable)

                {

                    while (it.MoveNext())

                    {

                        int elem = (int)it.Current;

                        Console.WriteLine(elem.ToString());

                    }

                }

    也即是说再出了foreach语句之后对于IEnumerator的对象也进行IDispose处理.

    foreach的两种限制

    不能修改枚举成员:

    int[] array = new int[100];

                foreach (var item in array)

                {

                    item++;//这是错误的,因为枚举成员是只读的

                    Console.WriteLine(item.ToString());

                }

    不要对集合进项删除操作:

    int[] array = new int[100];

                ArrayList alist = new ArrayList();

                alist.AddRange(array);

                foreach (var item in alist)

                {

                    alist.Remove(item);//这是错误的

                    Console.WriteLine(item.ToString());

                }

    对于删除成员和修改成员可以使用for循环来处理,对于一个记录集的多条数据删除问题,也是经常出现的问题,由于在一些记录集中进行删除的时候,在删除操作之后相应的索引也发生了变化,这时候的删除要反过来进行删除:

    int[] array = new int[100];

                ArrayList alist = new ArrayList();

                alist.AddRange(array);

                for (int i = alist.Count-1; i >=0; i--)

                {

                    int n = (int)alist[i];

                    if (n==5)

                    {

                        alist.RemoveAt(i);

                    }

                    Console.WriteLine(n.ToString());

                }

    除了上述提到的foreach的两个约束外,foreach可以用于人和循环.

    yield语句

    C#中的yield语句便于创建枚举器.

    yield语句的两种形式:

    1.yield return <expression>

    2.yield break;

    使用一个yield return语句返回集合的一个元素

    包含yield语句的方法或属性是迭代器.迭代器必须满足下列要求:

    a.返回类型必须是IEnumerable,IEnumerable<T>,IEnumeratorIEnumerator<T>

    b.他不能有任何refout参数.

    yield return语句不能位于try-catch;yield return语句可以位于try-finallytry

    yield return语句返回集合的一个元素,并移动到下一个元素上.yield break可以停止迭代.

    class Program

        {

            static void Main(string[] args)

            {

                HelloCollection hello = new HelloCollection();

                foreach(string item in hello)

                {

                    Console.WriteLine(item);                

                }

                Console.ReadKey();  

            }

        }

        public class HelloCollection

        {

            public  IEnumerator<string> GetEnumerator()

            {

                //yield return语句返回集合的一个元素,并移动到下一个元素上

                //yield break可以终止迭代

                yield return "hello";

                yield return "world";

            }

    }

    使用yield return语句实现以不同方式迭代集合的类:

    using System;

    using System.Collections;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace 枚举

    {

        class Program

        {

            static void Main(string[] args)

            {

                MusicTitles music = new MusicTitles();

                foreach(var item in music.GetEnumerator())

                {

                    Console.WriteLine(item);

                }

                Console.WriteLine();

                foreach (string item in music.Reverse())

                {

                    Console.WriteLine(item);

                }

                Console.WriteLine();

                foreach (var item in music.Subset(2,2))

                {

                    Console.WriteLine(item);

                }

                Console.ReadKey();  

            }

        }

        public class MusicTitles

        {

            string[] names = {"a","b","c","d" };

            public IEnumerable<string> GetEnumerator()

            {

                foreach (string item in names)

                {

                    yield return item;

                }

            }

            public IEnumerable<string> Reverse()

            {

                for (int i = 3; i >=0; i--)

                {

                    yield return names[i];

                }

            }

            public IEnumerable<string> Subset(int index, int offert)

            {

                for (int i = index; i < index+offert; i++)

                {

                    yield return names[i];

                }

            }

        }

    }

  • 相关阅读:
    HYSBZ 3813 奇数国
    HYSBZ 4419 发微博
    HYSBZ 1079 着色方案
    HYSBZ 3506 排序机械臂
    HYSBZ 3224 Tyvj 1728 普通平衡树
    Unity 3D,地形属性
    nginx 的naginx 种包含include关键字
    Redis 出现NOAUTH Authentication required解决方案
    mysql 8.0出现 Public Key Retrieval is not allowed
    修改jar包里的源码时候需要注意的问题
  • 原文地址:https://www.cnblogs.com/FinleyJiang/p/7602577.html
Copyright © 2011-2022 走看看