zoukankan      html  css  js  c++  java
  • IEnumerable和IEnumerator接口

    我们先思考几个问题:
    1.为什么在foreach中不能修改item的值?(IEnumerator的Current为只读)
    2.要实现foreach需要满足什么条件?(实现IEnumerator接口来实现的)
    3.为什么Linq to Object中要返回IEnumerable?(因为IEnumerable是延迟加载的,每次访问的时候才取值。也就是我们在Lambda里面写的where、select并没有循环遍历(只是在组装条件),只有在ToList或foreache的时候才真正去集合取值了。这样大大提高了性能。)

    .net中迭代器是通过IEnumerable和IEnumerator接口来实现的,今天我们也来依葫芦画瓢。

    using System;
    using System.Collections;
    
    namespace RedisTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                string[] str = { "1111", "2222", "3333", "4444", "5555" };
                var aaa = new MyIEnumerable(str);
                var bbb = aaa.GetEnumerator();
                while (bbb.MoveNext())
                {
                    Console.WriteLine(bbb.Current);
                }
                Console.WriteLine("---------------------------------------------------------");
                foreach (var item in aaa)
                {
                    Console.WriteLine(item);
                }
                Console.Read();
                /*
                1111
                2222
                3333
                4444
                5555
                ---------------------------------------------------------
                1111
                2222
                3333
                4444
                5555
                */
            }
        }
    
        public class MyIEnumerable : IEnumerable
        {
            private string[] strList;
            public MyIEnumerable(string[] _strList)
            {
                strList = _strList;
            }
            public IEnumerator GetEnumerator()
            {
                return new MyIEnumerator(strList);
            }
        }
    
        public class MyIEnumerator : IEnumerator
        {
            private string[] strList;
            private int position;
    
            public MyIEnumerator(string[] _strList)
            {
                strList = _strList;
                position = -1;
            }
            public object Current
            {
                get
                {
                    return strList[position];
                }
            }
    
            public bool MoveNext()
            {
                position++;
                if (position < strList.Length)
                    return true;
                return false;
            }
    
            public void Reset()
            {
                position = -1;
            }
        }
    }

    yield的使用

    using System;
    using System.Collections;
    
    namespace RedisTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                string[] str = { "1111", "2222", "3333", "4444", "5555" };
                var aaa = new MyIEnumerable(str);
                var bbb = aaa.GetEnumerator();
                while (bbb.MoveNext())
                {
                    Console.WriteLine(bbb.Current);
                }
                Console.WriteLine("---------------------------------------------------------");
                foreach (var item in aaa)
                {
                    Console.WriteLine(item);
                }
                Console.Read();
                /*
                1111
                2222
                3333
                4444
                5555
                ---------------------------------------------------------
                1111
                2222
                3333
                4444
                5555
                */
           
            }
        }
    
        public class MyIEnumerable
        {
            private string[] strList;
            public MyIEnumerable(string[] _strList)
            {
                strList = _strList;
            }
            public IEnumerator GetEnumerator()
            {
                for (int i = 0; i < strList.Length; i++)
                {
                    yield return strList[i];
                }
            }
        }
    
    
    }

    我们调用GetEnumerator的时候,看似里面for循环了一次,其实这个时候没有做任何操作。只有调用MoveNext的时候才会对应调用for循环:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace RedisTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                string[] str = { "1111", "2222", "3333", "4444", "5555" };
                var aaa = new MyIEnumerable(str);
                var bbb = aaa.MyWhere(x => x != "1111");
                var ccc = bbb.ToList();
                //现在看到了吧。执行到MyWhere的时候什么动作都没有(返回的就是IEnumerable),只有执行到ToList的时候才代码才真正的去遍历筛选。
                //这里的MyWhere其实可以用扩展方法来实现,提升逼格。(Linq的那些查询操作符就是以扩展的形式实现的)
                Console.Read();
    
    
            }
        }
    
        public class MyIEnumerable
        {
            private string[] strList;
            public MyIEnumerable(string[] _strList)
            {
                strList = _strList;
            }
            public IEnumerator GetEnumerator()
            {
                for (int i = 0; i < strList.Length; i++)
                {
                    yield return strList[i];
                }
            }
            public IEnumerable<string> MyWhere(Func<string, bool> func)
            {
                foreach (string item in this)
                {
                    if (func(item))
                    {
                        yield return item;
                    }
                }
            }
        }
    
    
    }
  • 相关阅读:
    English,The Da Vinci Code, Chapter 23
    python,meatobject
    English,The Da Vinci Code, Chapter 22
    English,The Da Vinci Code, Chapter 21
    English,The Da Vinci Code, Chapter 20
    English,The Da Vinci Code, Chapter 19
    python,xml,ELement Tree
    English,The Da Vinci Code, Chapter 18
    English,The Da Vinci Code, Chapter 17
    English,The Da Vinci Code, Chapter 16
  • 原文地址:https://www.cnblogs.com/lgxlsm/p/6758150.html
Copyright © 2011-2022 走看看