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

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

作者: 横刀天笑  来源: 博客园  发布时间: 2008-09-23 13:15  阅读: 11706 次  推荐: 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


调用迭代器的MoveNext()方法,L_004e: brtrue.s L_0036 如果是true的话跳转,

L_0036: ldloc.2 
L_0037: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
L_003c: stloc.1 
L_003d: ldloc.1 
L_003e: callvirt instance string [mscorlib]System.Object::ToString()
L_0043: call void [mscorlib]System.Console::WriteLine(string)

获取当前值,然后输出看到没有,实际foreach后面干的事就是获取迭代器,然后一个while循环,不过这样一些确实简洁多了。说到这里是不是

 IEnumerator ienumerator = list.GetEnumerator();
            
while (ienumerator.MoveNext())
            {
                
object item = ienumerator.Current;
                Console.WriteLine(item.ToString());
            }

foreach (object item in list)

Console.WriteLine(item.ToString());
}

这两样代码是一样的呢?如果不一样那推荐使用哪一个呢?当然是使用第二种,简洁嘛,除了简洁之外就没有其它的了?细心读者会发现上面的IL代码,在结束循环后还有一大块,可我们的C#代码中并没有啊,接着分析:

.try L_0034 to L_0052 finally handler L_0052 to L_0063

这里说明从L_0034到L_0052是被放在try里面的,恰好这段代码是循环体里的东西,L_0052到L_0063里是放在finally里的,看来foreach还给我们加了一个try{}finally{}结构啊。那看看L_0052到L_0063里是什么东西吧:

L_0052: ldloc.2 
    
L_0053: isinst [mscorlib]System.IDisposable
    
L_0058: stloc.3 
    
L_0059: ldloc.3 
    
L_005a: brfalse.s L_0062
    
L_005c: ldloc.3 
    
L_005d: callvirt instance void [mscorlib]System.IDisposable::Dispose()
    
L_0062: endfinally 
    
L_0063: call string [mscorlib]System.Console::ReadLine()

判断迭代器对象是否是一个IDisposable实例,如果是,那就要调用它的Dispose()方法了(为啥它要实现IDisposable接口?那肯定这个迭代器里使用了一些非托管资源)。 看到了吧,foreach也真够智能的,看来使用foreach的方式是比自己用while方式安全稳定多了。

(PS:好像是扯远了点,不过大家一起了解一下,呵呵,其实我当初也没想说这个,不过后来看IL代码有点不对劲,就当作个副产品吧)C# 2.0里还出现个关键字yield,我看了半天MSDN也没明白它的意思:

在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。到现在还是没明白,不过yield这个东西后面却包含了很多东西,有一些非常“奇怪”的特性, 我称之为奇怪的意思是与我们以前的思维有的不符,Linq的一些特质也是建立在这个特性之上的。关于yield的更多讨论我想放在另外一篇文章中,因为我觉得有必要。

4
0
标签:linq C# 迭代器

数据库热门文章

    数据库最新文章

      最新新闻

        热门新闻