是的,编译器、抖动和 CLR 的三元组有很多内置的数组知识。这对于任何语言运行时都是相当重要的,它不能忽略处理器的功能。为了使代码高效运行,它必须映射到处理器可以做得很好的地方。
这不是很多,处理器是相当简单的设备。它们没有为您喜欢在程序中使用的那种数据结构提供真正的支持。语言和运行时的设计方式显示了许多底层处理器实现细节。
例如,堆栈的概念无处不在。处理器可以通过其堆栈指针直接访问的少量内存。这就是为什么 C# 语言与几乎所有语言一样,在方法中具有局部变量的概念。这是一个将存储在堆栈中的变量。处理器还强烈支持使用返回单个值的参数调用方法的概念,这在任何语言中都是通用的。为堆栈分配的少量内存为该站点命名。
值类型是底层处理器细节的另一个 .NET 示例。它们直接映射到处理器在处理值时擅长的领域。例如,一个int直接映射到处理器寄存器。Float 和 double 直接映射到处理器存储这些值并使用这两种类型执行浮点指令的能力。
数组是处理器可以支持的唯一且唯一的数据结构。很简单,一块内存,带有访问该内存的指针。 在.NET中进行了高度优化,以使其尽可能高效。特别向“向量”致敬,这是一种经过特殊处理的数组类型。起始索引为 0 的一维数组,该数组类型直接映射到处理器支持。你在 C# 中得到一个向量type[]
宣言。您还可以从中看到数组限制,.NET 使创建一个起始索引不为 0 的数组变得非常困难。出于一个很好的理由,索引这样的数组是昂贵的,因为它需要额外的减法来映射内存块的索引。数组索引检查是另一个重要的优化目标,边界检查是昂贵的。抖动内置了许多智能,以识别循环永远不能索引数组越界,从而完全消除索引检查。
任何数据结构都需要建立在仅对裸阵列的处理器支持之上。这就是为什么您发现在 .NET 集合类中完成了该操作。没有来自 CLR 或抖动的额外帮助,因为他们几乎无法使其更快。这也是这些集合类都构建在向量数组之上的原因。像 List<> 一样,根本不是一个类似于您在数据算法教科书中看到的那种列表,实际上是一个数组。或者 Dictionary<>,一个数组的对立面,但仍然用它们实现。