您的位置:知识库 » 数据库

不能不说的C#特性-迭代器(上)及一些研究过程中的副产品

作者: 横刀天笑  来源: 博客园  发布时间: 2008-09-23 13:15  阅读: 11654 次  推荐: 4   原文链接   [收藏]  

系列文章导航:

走进Linq--Linq横空出世篇

走进Linq-辉煌的背后

走进Linq-Linq大观园

不能不说的C#特性-对象集合初始化器

不能不说的C#特性-匿名类型与隐式类型局部变量

不能不说的C#特性-扩展方法

不能不说的C#特性-匿名方法和Lambda表达式

不能不说的C#特性-迭代器(上)及一些研究过程中的副产品

不能不说的C#特性-迭代器(下),yield以及流的延迟计算

走进Linq-Linq to Objects(上)基础篇

走进Linq-Linq to Objects(下)实例篇

走进Linq-Linq to SQL感性认识篇

走进Linq-Linq to SQL How do I(1)

走进Linq-Linq to SQL How do I(2)

走进Linq-Linq to SQL How do I(3)

走进Linq-How do I(4)拾遗补零篇第一节

走进Linq-Linq to SQL源代码赏析 Table的获取过程

走进Linq-Linq to SQL源代码赏析之Provider的初始化

走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq


看看最后的测试,是不是不管具体的集合如何改变,遍历代码都非常稳定?而且扩展新的集合类也非常方便,只是添加代码不会修改原来的代码,符合开闭原则。当然,这么好的解决方案微软当然不会放过,现在C# 2.0里已经内置了对迭代器的支持,看看System.Collections, System.Collections.Generic命名空间,所有的集合都实现了这个接口:IEnumerable,这个接口还有泛型的版本。注意到这个接口只有一个方法:IEnumerator GetEnumerator();,IEnumerator就是迭代器的接口,相当于我的实例里面的Iterator,它也有泛型的版本。

那么现在在.net里所有的集合类都可以这样访问了:

IEnumerator ienumerator = list.GetEnumerator();
while(ienumerator.MoveNext())
{
    
object current = ienumerator.Current;
}

但是这样访问也太麻烦了,所以C#里出现了foreach关键字,我们来看看foreach背后发生了什么

public static void Main()
{            
            ArrayList list 
= new ArrayList();
            list.Add(
1);
            list.Add(
2);
            list.Add(
3);
            
foreach (object item in list)
            
{
                Console.WriteLine(item.ToString());
            }

}

下面是它对应的IL代码:

Code

从.locals init 那里可以看出编译器为我们添加了两个局部变量,一个就是迭代器。

L_002d: ldloc.0 
L_002e: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.ArrayList::GetEnumerator()
L_0033: stloc.2 

这三行代码告诉我们,调用list的GetEnumerator()方法,获取迭代器实例将其赋值给编译器为我们添加的那个迭代器局部变量,接着是L_0034: br.s L_0048,br.s这个指令是强制跳转,我们接着看

L_0048: ldloc.2 
L_0049: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
4
0
标签:linq C# 迭代器

数据库热门文章

    数据库最新文章

      最新新闻

        热门新闻