C#中的IEnumerable

在MSDN上,是这么说的,它是一个公开枚举数,该枚举数支持在非范型集合上进行简单的迭代。

参考资料(非常好):

https://www.cnblogs.com/fangyz/p/5721269.html

https://blog.csdn.net/weixin_42339460/article/details/80733758

以下为本人的调试代码:

代码1:

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

namespace 学习IEnumerable
{
    class Program
    {
        static void Main(string[] args)
        {
            FruitShop fruitShop = new FruitShop();
            Fruit fruitApple = new Fruit("Apple","10");
            Fruit fruitPear = new Fruit("Pear","12");
            Fruit fruitGrape = new Fruit("Grape","15");
            fruitShop.Add(fruitApple);
            fruitShop.Add(fruitPear);
            fruitShop.Add(fruitGrape);

            //调用自己实现的迭代器
            foreach (Fruit f in fruitShop)
            {
                Console.WriteLine(f.fruitName + ":" + f.fruitPrice);
            }

            Console.WriteLine("=============================================");

            CastAndOfType();

            Console.ReadLine();
        }

        //学习IEnumerable接口的两个扩展方法Cast<>(),OfType<>()
        static void CastAndOfType()
        {
            ArrayList fruits = new ArrayList(4);
            fruits.Add("Apple");
            fruits.Add("Pear");
            fruits.Add(2);
            fruits.Add(5);

            //下面的语句会报错,因为ArrayList没有实现IEnumerable<T>接口,故无法使用标准查询运算
            //IEnumerable<string> s = fruits.Select(str => str);

            IEnumerable<string> s1 = fruits.Cast<string>();
            IEnumerable<string> s2 = fruits.OfType<string>();
            //虽然Cast<T>和OfType<T>都可以用来进行转换,但是OfType<T>比Cast<T>更加强大,
            //它可以对结果进行筛选,而Cast<T>遇到无法强制转换的则会报错

            try
            {
                foreach (string fruit in s1)
                {
                    Console.WriteLine(fruit);
                }
            }
            catch (InvalidCastException invalid)
            {
                Console.WriteLine(invalid.Message);
            }

            foreach (string fruit in s2)
            {
                Console.WriteLine(fruit);
            }
        }
    }

    public class Fruit
    {
        public string fruitName;
        public string fruitPrice;

        public Fruit(string fruitName, string fruitPrice)
        {
            this.fruitName = fruitName;
            this.fruitPrice = fruitPrice;
        }
    }

    public class FruitShop : IEnumerable
    {
        Fruit[] fruits = new Fruit[3];
        int current = 0;

        public void Add(Fruit fruit)
        {
            fruits[current] = fruit;
            current++;
        }

        public IEnumerator GetEnumerator()
        {
            return new FruitEnumerator(fruits);
        }
    }

    //实现接口定义的方法
    public class FruitEnumerator : IEnumerator
    {
        Fruit[] fruits;
        int current = -1;

        public FruitEnumerator(Fruit[] fruits)
        {
            this.fruits = fruits;
        }

        public object Current
        {
            get
            {
                return CurrentFruit();
            }
        }

        object CurrentFruit()
        {
            if (current < 0 || current > fruits.Length)//此处是不是应该减1
                return null;
            else
                return fruits[current];
        }

        public bool MoveNext()
        {
            current++;
            if (current < fruits.Length && fruits[current] != null)
                return true;
            else
                return false;
        }

        public void Reset()
        {
            current = 0;
        }
    }
}

代码2:

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

namespace 深入学习IEnumerable
{
    class Program
    {
        static void Main(string[] args)
        {
            FruitShop fruitShop = new FruitShop();
            Fruit fruitApple = new Fruit("Apple");
            Fruit fruitPear = new Fruit("Pear");
            Fruit fruitGrape = new Fruit("Grape");
            fruitShop.Add(fruitApple);
            fruitShop.Add(fruitPear);
            fruitShop.Add(fruitGrape);

            IEnumerable<Fruit> s1 = fruitShop as IEnumerable<Fruit>;
            IEnumerable<Fruit> s2 = MyCast(fruitShop);

            Console.WriteLine("s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2s2");
            foreach (Fruit str in s2)
            {
                Console.WriteLine(str.fruitName);
            }

            //Console.WriteLine("s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1s1");
            //foreach (Fruit str in s1)
            //{
            //    Console.WriteLine(str.fruitName);
            //}

            Console.ReadLine();
        }

        static IEnumerable<Fruit> MyCast(FruitShop fruitShop)
        {
            IEnumerable<Fruit> typedSource = fruitShop as IEnumerable<Fruit>;
            if (typedSource != null)
                return typedSource;

            if (fruitShop == null)
                throw new Exception("fruitShop == null");

            return CastIterator<Fruit>(fruitShop);
        }

        static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source)
        {
            foreach (object obj in source)
            {
                yield return (TResult)obj;
            }
        }
    }

    public class Fruit
    {
        public string fruitName;
        public string fruitPrice;

        public Fruit(string fruitName, string fruitPrice = "10")
        {
            this.fruitName = fruitName;
            this.fruitPrice = fruitPrice;
        }
    }

    public class FruitShop : IEnumerable
    {
        Fruit[] fruits = new Fruit[3];
        int current = 0;

        public void Add(Fruit fruit)
        {
            fruits[current] = fruit;
            current++;
        }

        public IEnumerator GetEnumerator()
        {
            return new FruitEnumerator(fruits);
        }
    }

    //实现接口定义的方法
    public class FruitEnumerator : IEnumerator
    {
        Fruit[] fruits;
        int current = -1;

        public FruitEnumerator(Fruit[] fruits)
        {
            this.fruits = fruits;
        }

        public object Current
        {
            get
            {
                return CurrentFruit();
            }
        }

        object CurrentFruit()
        {
            if (current < 0 || current > fruits.Length)//此处是不是应该减1
                return null;
            else
                return fruits[current];
        }

        public bool MoveNext()
        {
            current++;
            if (current < fruits.Length && fruits[current] != null)
                return true;
            else
                return false;
        }

        public void Reset()
        {
            current = 0;
        }
    }
}

代码3:

using System;
using System.Collections;

namespace 再次深入学习IEnumerable
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] strList = new string[] { "chenwei","male","15601598187"};
            MyIEnumerable my = new MyIEnumerable(strList);

            Console.WriteLine("==========开始调用自己实现的迭代器==========");
            //第一步:获取IEnunerator接口实例
            var tst = my.GetEnumerator();

            //第二步:判断是否可以继续循环
            while (tst.MoveNext())
            {
                //第三步:取值
                Console.WriteLine(tst.Current);
            }

            Console.WriteLine("通过foreach来取值(效果同上,因为IL代码是一样的)");
            foreach (var item in my)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }
    }

    //为什么都用数组做容器?可以用List吗???
    //可以

    //.net中迭代器是通过IEnumerable和IEnumerator接口来实现的。
    //可以照葫芦画瓢,实现自己的迭代器。
    //IEnumerable只有一个返回IEnumerator的GetEnumerator方法。
    //而IEnumerator中有两个方法加一个属性。
    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;
        }

        //因为只有get没有set,所以foreach中不能修改item的值
        public object Current
        {
            get{return strList[position];}
        }

        public bool MoveNext()
        {
            position++;
            if(position < strList.Length)
                return true;
            else
                return false;
        }

        public void Reset()
        {
            position = -1;
        }
    }
}

代码4:

using System;
using System.Collections;

namespace 实现foreach需要满足什么条件
{
    //继“再次深入学习IEnumerable”之后,有如下疑问:
    //实现foreach需要什么条件?
    //必须实现IEnumerable接口?NO!
    //我们把自己写的MyIEnumerable删掉后面的IEnumerable接口一样可以foreach。
    //所以要可以foreach只需要对象定义了GetEnumerator无参方法,并且返回值是IEnumerator或其对应的范型。
    //也就是说,只要三步就可以了,不一定要继承与IEnumerable。
    //第一步:“获取IEnumerator实例”
    //第二步:“判断是否可以继续循环”
    //第三步:“取值”
    class Program
    {
        static void Main(string[] args)
        {
            string[] strList = new string[] { "chenwei", "male", "15601598187" };
            MyIEnumerable my = new MyIEnumerable(strList);

            Console.WriteLine("==========开始调用自己实现的迭代器==========");
            //第一步:获取IEnunerator接口实例
            var tst = my.GetEnumerator();

            //第二步:判断是否可以继续循环
            while (tst.MoveNext())
            {
                //第三步:取值
                Console.WriteLine(tst.Current);
            }

            Console.WriteLine("通过foreach来取值(效果同上,因为IL代码是一样的)");
            foreach (var item in my)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }
    }

    public class MyIEnumerable
    {
        private string[] strList;

        public MyIEnumerable(string[] _strList)
        {
            strList = _strList;
        }

        public IEnumerator GetEnumerator()
        {
            return new MyIEnumerator(strList);

            //实际连MyIEnumerator都可以不要,yield就可以了。
            //for (int i = 0; i < strList.Length; i++)
            //{
            //    yield return strList[i];
            //}
        }
    }

    public class MyIEnumerator : IEnumerator
    {
        private string[] strList;
        private int position;

        public MyIEnumerator(string[] _strList)
        {
            strList = _strList;
            position = -1;
        }

        //因为只有get没有set,所以foreach中不能修改item的值
        public object Current
        {
            get { return strList[position]; }
        }

        public bool MoveNext()
        {
            position++;
            if (position < strList.Length)
                return true;
            else
                return false;
        }

        public void Reset()
        {
            position = -1;
        }
    }
}

 

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值