c# – LINQ缓存计算值吗?

假设我有以下代码
var X = XElement.Parse (@"
    <ROOT>
        <MUL v='2' />
        <MUL v='3' />
    </ROOT>
");
Enumerable.Range (1,100)
    .Select (s => X.Elements ()
        .Select (t => Int32.Parse (t.Attribute ("v").Value))
        .Aggregate (s,(t,u) => t * u)
    )
    .ToList ()
    .ForEach (s => Console.WriteLine (s));

什么是.NET运行时实际在这里做什么?它是解析并将属性转换为100次中的每一个整数,还是足够智能,以确定它应该缓存解析的值而不重复该范围中每个元素的计算?

而且,我怎么会自己搞清楚这样的事情呢?

在此先感谢您的帮助.

解决方法

自从我挖掘这段代码以来已经有一段时间了,但是,IIRC,Select工作的方式就是简单地缓存你提供它的Func并一次在源集合上运行它.因此,对于外部范围中的每个元素,它将运行内部Select / Aggregate序列,就像它是第一次一样.没有任何内置缓存 – 您必须在表达式中自己实现.

如果你想自己解决这个问题,你有三个基本选择:

>编译代码并使用ildasm查看IL;它是最准确的,特别是对于lambdas和闭包,你从IL获得的东西可能看起来与你放入C#编译器的东西完全不同.
>使用像dotpeek这样的东西将System.Linq.dll反编译成C#;再一次,你从这些工具中获得的东西可能只是大致类似于原始的源代码,但至少它将是C#(特别是dotpeek做得非常好,并且是免费的.)
>我的个人偏好 – 下载.NET 4.0 Reference Source并自己寻找;这就是它的用途:)您必须只信任MS,参考源与用于生成二进制文件的实际源匹配,但我认为没有任何理由怀疑它们.>正如@AllonGuralnek所指出的,你可以在一行内的特定lambda表达式上设置断点;将光标放在lambda体内的某个位置并按F9,它将断点为lambda. (如果你做错了,它会突出显示断点颜色的整行;如果你做得对,它只会突出显示lambda.)

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...