C#常用集合都实现了ICollection和IEnumerable接口,这是能使用foreach的关键所在。而我们自定义的集合,IEnumerable中定义定义了一个GetEnumerator()方法,IEnumerator依靠MoveNext和Current来达到Foreach的遍历。第一次遇到foreach里的对象时就会去执行继承IEnumerable类中的GetEnumerator方法,接着每次执行in关键字就会去执行MoveNext方法,每次取数据则是调用Current属性。IEnumerable接口并不是我们看到的只有一个方法,它还有4个扩展方法。其中Cast<T>()和OfType<T>()这2个方法非常实用,代码如下所示。有时候对于非泛型集合比如ArrayList,它只实现了IEnumerable接口而没有实现IEnumerable<T>接口,因此无法使用标准查询运算。
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<fruits.Length&&fruits[current]!=null)
return true;
return false;
}
public void Reset()
{
current=0;
}
}
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);
}
}
}
Cast<T>()和OfType<T>()使用:
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=fruitShop.Select(str => str);
//但是使用Cast<T>和OfType<T>来进行转换
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);
}
}
参考:https://blog.csdn.net/csdnsunyf/article/details/102666945