C#基础复习IEnumerable(和 yield return的使用滴呀 )

IEnumerable 真是基础中的基础,然而.....

我们直接来看看这个接口的实现吧;

它是一个公开枚举数,该枚举数支持在非泛型集合上进行简单的迭代。换句话说,对于所有数组的遍历,都来自IEnumerable,那么我们就可以利用这个特性,来定义一个能够遍历xxxxxx的通用方法

先看我们的经典实例1:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4
{

    public class Person:IEnumerable
    {
        public string name;

        public int age;

        public Person(string _name, int _age)
        {
            name = _name;
            age = _age;
        }

        private Person[] per;

        public Person(Person[] arr)
        {
            per=new Person[arr.Length];

            for (int i = 0; i < arr.Length; i++)
            {
                per[i] = arr[i];
            }

        }

        //实现这个接口;
        public IEnumerator GetEnumerator()
        {
            return new PersonEnum(per);
        }

    }

     class PersonEnum : IEnumerator//实现foreach语句内部,并派生
     {

         public Person[] _per; //实现数组;
         int position = -1;
         public PersonEnum(Person[] list)
         {
             _per = list;
         }

         public bool MoveNext()
         {
             position++;
             return (position < _per.Length);
         }

         public void Reset()
         {
             position = -1;
         }
         public object Current   //实现接口的方法;
         {
             get
             {
                 try
                 {
                     return _per[position];
                 }
                 catch (IndexOutOfRangeException)
                 {
                     throw new InvalidOperationException();//抛出异常信息
                 }
             }
         }
     }

    class Program
    {

        static void Main(string[] args)
        {
            Person[] per = new Person[2] 

            {

                new Person("guojing",21), 

                new Person("muqing",21), 

            };

            //这个。我们就可以进行枚举了;
            Person personlist = new Person(per);

            foreach (Person p in personlist)  //本质上是对数组的枚举,还是通过我们的额index 来实现的滴呀;,只不过要支持foreach的写法,自然要实现我们的ienumberable的重写;
            {
                Console.WriteLine("Name is " + p.name + " and Age is " + p.age);
                //本质上是一种写法的改变滴呀;
            }

            var obj=new Person("muqing", 21);
            foreach (var p in obj)
            {
                //Console.WriteLine("Name is " + p.name + " and Age is " + p.age); bug
            }

            Console.ReadLine();

        }
    }
}

再看我们经典实例二:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication5
{
    public class charlist : IEnumerable
    {
        private string TargetStr { get; set; }

        public charlist(string str)
        {
            this.TargetStr = str;
        }

        public IEnumerator GetEnumerator()
        {
            return new charIterator(TargetStr);
        }

    }

    public class charIterator:IEnumerator
    {
        public string TargetString { get; set; }

        public int position { get; set; }

        public charIterator(string str)
        {
            this.TargetString = str;
            this.position = this.TargetString.Length;
        }

        public object Current
        {
            get
            {
                if (this.position == -1 || this.position == this.TargetString.Length)
                {
                    throw new InvalidOperationException();
                }
                return this.TargetString[this.position];
            }
        }

        public bool MoveNext()
        {
            if (this.position != -1)
            {
                 this.position--;
            }
            return this.position > -1;
        }

        public void Reset()
        {
            this.position = this.TargetString.Length;
        }

    }

    class Program
    {
        static void Main(string[] args)
        {

            //我这里是倒着枚举出来滴哎呦;
            string val = "fuck the life";
            charlist list = new charlist(val);
            foreach (var o in list)
            {
                Console.WriteLine(o);
            }
            Console.ReadLine();

        }
    }
}

这里顺便提一下我们的 yield  return 用法的复习和使用滴呀;

上面的两种实现方式可以说是我们net 1.0 的各种常见做法滴呀;

后面,我们将尝试yield return的用法;

 for (int index = this.TargetStr.Length; index > 0;index-- )

      {

        yield return this.TargetStr[index - 1];

      }

关于我们的yield return的使用;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication6
{

    class Program
    {
        /// <summary>
        /// 获取数据
        /// </summary>
        /// <returns></returns>
        static List<int> GetData()
        {
            return new List<int>() { 1, 2, 3, 4 };
        }

        static IEnumerable<int> WithoutYield()
        {
            List<int> result = new List<int>();
            foreach (var i in GetData())
            {
                if (i > 2)
                {
                     result.Add(i);
                }
            }
            return result;
        }

        static IEnumerable<int> WithYield()
        {
            foreach (var i in GetData())
            {
                if (i > 2)
                {
                    yield return i;
                }
            }
        }

        static void Main(string[] args)
        {

            Console.WriteLine("不使用我们的额yield return的结果;");
            foreach(var val in WithoutYield())
            {
                Console.WriteLine(val);
            }

            Console.WriteLine("使用我们的额yield return的结果;");
            foreach (var val in WithYield())
            {
                Console.WriteLine(val);
            }
            //如果使用我们的f11 调试你会发现,yield 是取出一个就马上返回一个,效果是非常好滴呀;
            //而第一个的做法,是得到所有的结果之后在一次性返回;
            Console.ReadLine();

        }
    }
}

通过调试发现:两种方法的输出结果是一样的,但实际的运作过程是不同的。

第一种方法,是把结果集全部加载到内存中再遍历;

第二种方法,遍历每调用一次,yield return就返回一个值;

因此,当希望获取一个IEnumerable<T>类型的集合,而不想把数据一次性加载到内存,就可以考虑使用yield return的方式去实现;

这里还得说说使用它的一个坑滴呀;

yield 语句只能出现在 iterator 块中,这种块可作为方法、运算符或访问器的主体实现。 这类方法、运算符或访问器的体受以下约束的控制:

  • 不允许不安全块。
  • 方法、运算符或访问器的参数不能是 ref 或 out
  • yield return 语句不能放在 try-catch 块中的任何位置。 该语句可放在后跟 finally 块的 try 块中。
  • yield break 语句可放在 try 块或 catch 块中,但不能放在 finally 块中。

重点是,不能放在我们的try catch 语句中滴呀;

时间: 2024-10-11 07:36:48

C#基础复习IEnumerable(和 yield return的使用滴呀 )的相关文章

IEnumerator/ IEnumerable/ yield return/ StartCoroutine 详解

IEnumerator/ IEnumerable public interface IEnumerable { IEnumerator GetEnumerator(); } public interface IEnumerator { bool MoveNext(); void Reset(); Object Current { get; } } 在两者的使用上,有下面几点需要注意 1.一个Collection要支持foreach方式的遍历,必须实现IEnumerable接口(亦即,必须以某种方

C++基础复习

一. C++与C的比较: C语言是一个结构化语言,它的重点在于算法和数据结构,C语言的设计首先要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到的输出(或实现过程(事物)控制). C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事物)控制. 所以C语言和C++的最大区别在于它们解决问题的思想不同,一个面向过程一个面向对象. C++对C的"增强",表现在六个方面: 1.类型检测更为严格. 2.

C# yield return用法

本文实例讲述了C#中yield return用法,并且对比了使用yield return与不使用yield return的情况,以便读者更好的进行理解.具体如下: yield关键字用于遍历循环中,yield return用于返回IEnumerable<T>,yield break用于终止循环遍历. 有这样的一个int类型的集合: ? 1 2 3 4 static List<int> GetInitialData() {   return new List<int>(){

造轮子_C#中yield return用法分析

厂址: http://www.jb51.net/article/54810.htm static List<int> GetInitialData() {   return new List<int>(){1,2,3,4}; } 打印出所有值大于2的元素 不使用yield return的实现 static IEnumerable<int> FilterWithoutYield() {   List<int> result = new List<int&

yield return 和 yield break

//yield return 返回类型必须为 IEnumerable.IEnumerable<T>.IEnumerator 或 IEnumerator<T>. static IEnumerator<int> yieldTest() //yield return 返回IEnumerator  { yield return 1; yield return 4; if (true)//如果为True 输出 1,4;//如果是False 输出 1,4,3,2 { yield b

C# yield return 用法与解析

C# yield return 用法与解析 本文参考自:http://www.jb51.net/article/54810.htm 当初没有认真理解 yield 这个关键字,现在又遇到了依旧不理解,为了以后不再为了 yield 困惑,决定好好研究一下 yield 的用法与意义: yield 从字面上理解有“退位,屈服”的意思,转一下弯就理解成“权限转移”,也就是将控制权交给别人,在这里就是把集合里满足条件(如果没有过滤条件,就是全体)的个体的操作转移给另一个对象. class Program {

温故知新,基础复习(快速排序及优化)

温故知新,基础复习(快速排序及优化) 使用了三值取中和插排优化 #include<stdio.h> #define InsertSortNumber 10 void InsertSort(int Arra[],unsigned int LowIndex,unsigned int HighIndex) { printf("low=%d,high=%d\n",LowIndex,HighIndex); for (unsigned int i = LowIndex + 1; i &

温故知新,基础复习(二叉堆排序)

温故知新,基础复习(二叉堆排序) 最小堆(最终数组的数据是降序),最大堆(最终数组的数据是升序) 下例是最小堆 #include <stdio.h> #include <stdlib.h> void Swap(int Arra[],unsigned int LeftIndex,unsigned int RightIndex) { int TeampValue = Arra[LeftIndex]; Arra[LeftIndex]=Arra[RightIndex]; Arra[Righ

温故知新,基础复习(一个有序从大到小不重复的数列,任意给出一个sum值,求出数列中所有满足和为sum的数对)

温故知新,基础复习(一个有序从大到小不重复的数列,任意给出一个sum值,求出数列中所有满足和为sum的数对) #include<stdio.h> #include<stdlib.h> void PrintSumNumbers(int Arra[],int ASize,int Sum) { //O(1) if (ASize<2) { printf("The size of the Arra is invalid.\n"); return; } if(Sum&