C#CLR缓存字典是否查找结果?

C#CLR缓存字典是否查找结果?,c#,performance,dictionary,C#,Performance,Dictionary,为了清楚起见,下面的代码是执行类似的操作,还是后者可能更快?CLR会缓存来自字典的循环结果吗?我知道在这种特殊情况下应该使用switch,但如果我能更好地了解CLR将如何处理字典查找结果缓存,那就太好了 foreach (string columnName in csvReader.ReadFields()) { if (FieldType.Int == fieldTypes[columnName])

为了清楚起见,下面的代码是执行类似的操作,还是后者可能更快?CLR会缓存来自字典的循环结果吗?我知道在这种特殊情况下应该使用switch,但如果我能更好地了解CLR将如何处理字典查找结果缓存,那就太好了

            foreach (string columnName in csvReader.ReadFields())
            {
                if (FieldType.Int == fieldTypes[columnName])
                {
                    //do something
                }
                else if (FieldType.Double == fieldTypes[columnName])
                {
                    //do something
                }
                else if (FieldType.Datetime == fieldTypes[columnName])
                {
                    //do something
                }
                .....
                .....
                .....
            }
vs


索引器是方法,不能省略方法调用。因此,编译器/运行时不会将3个方法调用合并为一个。(更新:一些索引器可能是内联的,如果它们足够简单的话,就可以省略,但是
字典
的索引器不太可能发生这种情况)

然而,字典在恒定的O(1)时间内执行随机访问,因此性能在这里并不是问题(除非我们讨论的是微观优化,其中恒定因素可能很重要)


我会选择最具可读性的方法-依我看,这是第二种方法。

编译器会将第一种方法优化为第二种。@ikh:有任何证明链接吗?编译器绝对不会这样做。他不知道索引器会做什么,也不知道它是否有任何副作用,因此绝对不允许省略2个方法调用。通用子表达式消除是标准抖动优化之一。即使由于某种原因,它错过了优化,您也不会注意到它,因为读取CSV文件需要花费很多很多时间。当其他代码需要毫秒时,纳秒是无法测量的。程序的性能完全由I/O控制。要提高速度,需要更好的磁盘或网络。@HansPassant如果索引器有副作用怎么办?你确定他们可以被淘汰吗?我知道字段读/写可以,但我不认为方法调用可以…删除方法调用是抖动优化器的一个标准特性。请注意MethodImplOption.NoInLine枚举值,用于抑制优化。几乎任何属性或索引器方法调用都是内联的,除非它太不常用。字典的索引器是有意内联的,注意ThrowHelper类的使用。@HansPassant我认为
ThrowHelper
的目的是。它对内联有什么帮助?直接抛出异常的方法不是内联的。因为这使得从堆栈跟踪诊断异常变得太困难了。@HansPassant Aaah,有道理,内联抛出异常的方法会破坏堆栈跟踪。但是假设索引器真的是内联的(我认为内联太复杂了,但是我们假设它是内联的)。JIT是否只允许删除变量读取/存储(只要这些读取/存储符合的规则)?删除整个方法对我来说似乎太多了……当然,如果优化器发现内联索引器/属性没有任何有用的副作用,那么它会完全消除它。当然,字典索引器不会发生这种情况,因为它包含对非平凡内部方法的调用。
            foreach (string columnName in csvReader.ReadFields())
            {
                FieldType fieldType = fieldTypes[columnName];
                if (FieldType.Int == fieldType  )
                {
                    //do something
                }
                else if (FieldType.Double == fieldType)
                {
                    //do something
                }
                else if (FieldType.Datetime == fieldType )
                {
                    //do something
                }
                .....
                .....
                .....
            }