转载-------C#基础之IEnumerable

1.IEnumerable的作用

  在使用Linq查询数据时经常以IEnumerable来作为数据查询返回对象,在使用foreach进行遍历时需要该对象实现IEnumerable接口,这2个功能让我对IEnumerable充满了无穷的好奇。然而在VS中查看IEnumerable的定义时发现它只定义了一个GetEnumerator()方法,关于IEnumerator我知道它依靠MoveNext和Current来达到Foreach的遍历,但是具体是如何将数据进行迭代的,完整的流程是怎样的?这些疑虑我觉得只有亲自实现一次自定义集合foreach才能够解决。为此我需要定义一个集合FruitShop类,它是一个关于Fruit对象的集合,代码如下所示。整个流程是第一次遇到foreach里的fruitShop对象时就会去执行FruitShop中的GetEnumerator方法,接着每次执行in关键字就会去执行MoveNext方法,每次取数据则是调用Current属性。

  写完代码之后突然就觉得其实没什么了,不过在查找资料当中发现IEnumerable接口并不是我们看到的只有一个方法,它还有4个扩展方法。其中Cast()和OfType()这2个方法非常实用,代码如下所示。有时候对于非泛型集合比如ArrayList,它只实现了IEnumerable接口而没有实现IEnumerable接口,因此无法使用标准查询运算。但是标准查询运算如此的方便,.NET肯定不会允许这样的不完美发生,于是为IEnumerable提供了2个扩展方法。只要实现了IEnumerable接口的集合就可以使用这2个方法来进行强制转换。而OfType比Cast更加强大,它除了进行强制转换外还可以实现类型的过滤。从结果中可以看到第一个foreach遇到int类型后由于无法转换而报出InvalidCastException异常,而使用OfType进行转换时则会自动进行类型筛选,遇到int类型的数据将不会转换,所以进行转换时OfType是首选。

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


 class FruitShop:IEnumerable
    {
        Fruit[] fruits=new Fruit[10];
        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;
        }

        //这里需要做一个判断,因为有可能此时current<0或超出数组长度
        public object Current
        {
            get { return CurrentFruit(); }
        }
        object CurrentFruit()
        {
            if (current < 0 || current > fruits.Length)
                return null;
            else
                return fruits[current];
        }

        public bool MoveNext()
        {
            current++;
            if(current
static void CastAndOfType()
        {
            ArrayList fruits = new ArrayList(4);
            fruits.Add("Apple");
            fruits.Add("Pear");
            fruits.Add(2);
            fruits.Add(5);

            //下面这句会报错,因为ArrayList没有实现IEnumerable接口,故无法使用标准查询运算
            //IEnumerable s=fruitShop.Select(str => str);
            //但是使用Cast和OfType来进行转换

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

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

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

转载-------C#基础之IEnumerable_第1张图片

 

 

转载于:https://my.oschina.net/zhangqiliang/blog/1925713

你可能感兴趣的:(转载-------C#基础之IEnumerable)