1)为什么数组可以foreach遍历?
因为数组可以按需提供一个叫做枚举数(enumerator)的对象。该对象实现了IEnumerator接口。
提高一个层次说,所有被foreach遍历的对象实现了IEnumerable接口,在遍历时调用了该对象的GetEnumerator()反响。返回的是实现了 IEnumerator接口的对象。
枚举的三种形式:IEnumerable/IEnumerator形式、IEnumerable<T>/IEnumerator<T>泛型形式,不使用接口
也就是说,所有的数组默认实现了IEnemerator接口,包含三个方法 public object Current{get{return ;}} public bool MoveNext(){} public void Reset(){}
一个例子:
namespace ConsoleTest{ class Program { static void Main(string[] args) { MyColor colors = new MyColor();foreach (var color in colors)
{ Console.WriteLine(color); }Console.Read();
}
}
class MyColor : IEnumerable { public IEnumerator GetEnumerator() { string[] Colors = { "Red", "yellow", "Blue" }; return new ColorEnumerator(Colors); } }class ColorEnumerator : IEnumerator
{ String[] Colors; private int Position = -1; public object Current { get { return Colors[Position]; } }public bool MoveNext()
{ if (Position < Colors.Length - 1) { Position++; return true; } return false; }public void Reset()
{ Position = -1; } public ColorEnumerator(string[] theColors) { Colors = new string[theColors.Length]; for (int i = 0; i < theColors.Length; i++) { Colors[i] = theColors[i]; } } }}
2)linq to sql 查询
var q = from c in dbContext.Customers
where c.City == "shenzhen" select c;得到的结果是IQuerable类型,每次foreach时都得到数据库里拿。这样远程查询的好处是:可以利用数据库的索引,不会取到不用的数据。可以适用场景:foreach为1次,这样只需要查一次数据库。
而linq to object查询
var q = (from c in dbContext.Customers
where c.City == "shenzhen" select c).AsEnumerable();得到的结果则是IEnemerable<T>类型,每次foreach时,数据已经在本地的内存上了。适用场景: foreach次数多。以上所有的foreach都可以替换为count(),sum()等聚合函数,执行这些函数时,已经对数据源进行查询了。