• 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];

                }

            }

        }

    }

  • 相关阅读:
    2020阿里最新出品的泰山版Java开发手册,告别垃圾代码
    freecplus框架-目录操作
    freecplus框架简介
    freecplus框架-加载参数文件
    freecplus框架-xml解析
    freecplus框架-tcp网络通信
    freecplus框架-PostgreSQL数据库操作
    freecplus框架-Oracle数据库操作
    freecplus框架-MySQL数据库操作
    freecplus框架-ftp客户端
  • 原文地址:https://www.cnblogs.com/FinleyJiang/p/7602577.html
Copyright © 2020-2023  润新知