在C#中使用Array.GetLength(dimension)
时,每次调用数组时实际上是否计算了数组的大小,或者是否缓存/存储了该数组的大小并且该值才被访问?
我真正想知道的是,如果将一个局部变量设置为数组维度的长度,如果在一个大循环中使用,或者我可以一遍又一遍地调用array.GetLength(),则会增加任何效率o任何速度惩罚。
答案 0 :(得分:8)
在这里开始缓存/优化肯定是一个坏主意。
处理数组时,必须遵循(JIT)优化器可以识别的标准路径。如果这样做,不仅会缓存Length属性,更重要的是索引边界检查可以在循环之前完成一次。
当优化程序丢失您的踪迹时,您将支付每次访问边界检查的罚款。
这就是为什么锯齿状数组(int[][]
)比多维数(int[,]
)更快的原因。简化int[,]
的优化。无论如何,我还没有检查Fx4的状态。
如果您想进一步研究,您建议的缓存通常称为“hoisting”长度属性。
答案 1 :(得分:0)
如果已知,它可能在编译时插入。否则,存储在变量中。如果不是,那么如何计算尺寸?
但是,您不应该对框架的内部操作做出假设。如果你想知道某些东西是效率更高还是更低,请测试它!
答案 2 :(得分:0)
如果您确实需要尽可能快地循环,则可以将长度存储在变量中。这会给你带来轻微的性能提升,我做的一些快速测试表明它的速度提高了约30%。
由于差异不大,它表明GetLength
方法非常快。除非你真的需要填写代码的最后一个,否则你应该只使用循环中的方法。
仅适用于多维数组。对于单维数组,在循环中使用Length
属性实际上更快,因为优化器可以在循环中使用数组时删除边界检查。
答案 3 :(得分:-1)
命名约定是一个线索。 .net中的“Length”方法(例如Array.Length)通常返回已知值,而“Count”方法(例如List.Count)将/可以枚举集合的内容以计算项目数。 (在后面的.nets中有像Any这样的扩展方法,允许你检查集合是否为非空而不必使用可能很昂贵的Count操作)GetLength只应该与Length不同,因为你可以请求你想要长度的维度的。
局部变量在调用GetLength时不太可能有任何区别 - 编译器无论如何都会很好地优化大多数情况 - 或者你可以使用foreach,它不需要在开始之前确定长度。
(但是很容易编写几个循环并计时(使用高性能计数器)来查看不同的调用/类型对执行速度的影响。这种快速测试可以很好如果您只是阅读答案,那么获得对您可能不会真正接受的语言的见解的方式)