在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接口,故无法使用标准查询运算
//IEnumerable s = fruits.Select(str => str);
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);
}
}
}
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 s1 = fruitShop as IEnumerable;
IEnumerable 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 MyCast(FruitShop fruitShop)
{
IEnumerable typedSource = fruitShop as IEnumerable;
if (typedSource != null)
return typedSource;
if (fruitShop == null)
throw new Exception("fruitShop == null");
return CastIterator(fruitShop);
}
static IEnumerable CastIterator(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;
}
}
}