zoukankan      html  css  js  c++  java
  • 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 语句中滴呀; 我们直接放代码说话。感觉还是挺好的,今天我来加班,我快乐!

        public class Info
        {
            //你可以这样写
            public IEnumerable<Person> personList
            {
                get
                {
                    try
                    {
                        return new List<Person>()
                        {
                            new Person() { Name="jack",Age=12 },
                            new Person() { Name="jack",Age=13 }
                        };
                    }
                    catch (Exception ex)
                    {
                        return null;
                    }
    
                }
            }
    
    
            //或者这样写;
    
            public IEnumerable<Person> personListByYiled
            {
                get
                {
    
                    yield return new Person() { Name = "jack", Age = 12 };
                    yield return new Person() { Name = "jack", Age = 13 };
                }
            }
    
    
    
    
            //但是不可以这样写!!!!!!!!!!!!!!!!!
            public IEnumerable<Person> EorrPersonList
            {
                get
                {
                    try
                    {
                        yield return new Person() { Name = "jack", Age = 12 };
                        yield return new Person() { Name = "jack", Age = 13 };
                    }
                    catch (Exception ex)
                    {
                        return null;
                    }
    
                }
            }
    
    
        }

    这里,我们又提到了异常捕获,我们也讲究复习一下嘛;

            public class FuckLife
            {
                //这了我们俩看看try catch finally 中嵌套return的情况;
                //常规情况;
                public void Test()
                {
                    try
                    {
                        
                    }
                    catch(Exception ex)
                    {
    
                    }
                    finally
                    {
                        //大家知道finally 语句中的语句都会执行的
                        //那如果 catch 中有了 return,会是怎样的结果呢
                    }
                    Console.WriteLine("------");//没有return,这里的语句就会被执行;
                }
    
                public int Test1(int a,int b)
                {
                   
                    try
                    {
                         int    result = a / b;
                        return result;
                    }
                    catch (Exception ex)
                    {
                        return 0;//return 阻止了finally后面的代码,但是不会阻止finally 中的代码
                    }
                    finally
                    {
                        //那如果 catch 中有了 return,会是怎样的结果呢: 答案是会执行的;
                        //return 0;  finally 中,是不会有return的滴呀;
                        Console.WriteLine("finally");
                    }
                    return 100;  //就算是这有return,也无法访问;
                    Console.WriteLine("这里的语句,会不会执行呢,答案是不会的会的");
    
    
                }
    
                //总结:当catch 中有了return,finally中的语句还是会执行;但是finally之后的代码无法访问;
    
            }
    /总结:当catch 中有了return,finally中的语句还是会执行;但是finally之后的代码无法访问;
    return 阻止了finally后面的代码,但是不会阻止finally (里面)中的代码。


    我们来看看编译后的代码;
    我们可以看到,其实在try或者catch中return,相当于在声明了一个变量,把要return的值赋给变量,最后再在finally之后(其实是整个函数运行到最后)才返回这个变量

    所以......
    public class mssq
        {
            public int GetValue(int a ,int b)
            {
                int result = 0;  //没有必要将我们的return 嵌套在我们的try catch 语句中,直接申明一个结果变量来保存我们想要的值,就可以了
                try
                {
                    result = a / b;
                }
                catch(Exception ex)
                {
                    //异常信息不活,或者其他操作;
                    result = -1;
                }
                return result;
    
            }
        }







    这里在附加一个基础题的复习;
            //结果是1;
            static int getVal()
            {
                int times = 1;
                return times++; //先进行前面的return 运算 在++ 结果:1
            }
    
            static int getVal2()
            {
                int times = 1;
                return times = times + 1; //先加,再return  结果:2
            }
    
            static int getVal3()
            {
                int times = 1;
                return ++times;        //先加,再return 结果:2
            }
    
            //类似的一个经典题;
            static void getTest()
            {
                int i = 0;
                int j = 0;
                int iResult = i++;
                int jResult = ++j;
                Console.WriteLine(iResult); //0
                Console.WriteLine(jResult); //1
            }
  • 相关阅读:
    day5 元组、列表、字典和集合
    day4 字符串类型和列表类型的详细caozu
    day3 数据类型
    预习
    python基础
    计算机基础——老年人上网冲浪手册
    pycharm操作指北
    day1 计算机基础知识
    Securing a Laravel API in 20 minutes with JWTs
    Testing Api using PHPUnit Laravel
  • 原文地址:https://www.cnblogs.com/mc67/p/7214805.html
Copyright © 2011-2022 走看看