作为 dotnet 集合 Stack.cs 源代码
public T Peek()
{
int size = _size - 1;
T[] array = _array;
if ((uint)size >= (uint)array.Length)
{
ThrowForEmptyStack();
}
return array[size];
}
有后备数组的本地参考副本
T[] array = _array;
来源在这里
Collections 代码库中有很多类似的代码。
这样做的目的是什么?与线程安全或任何其他考虑有关吗?为什么不使用类字段
_array
来代替呢?
我在谷歌中找不到任何线索,所以期待在这里得到一些见解。
我不能肯定地说,但我希望这将是某种 JIT 优化。
猜测:虽然 JIT 确实有逻辑来进行边界检查省略,但如果您两次引用该字段而不是局部变量,它可能不起作用。
ThrowForEmptyStack
已知是无返回的:
private void ThrowForEmptyStack()
{
Debug.Assert(_size == 0);
throw new InvalidOperationException(SR.InvalidOperation_EmptyStack);
}
所以当代码进行检查时
if ((uint)size >= (uint)array.Length)
{
ThrowForEmptyStack();
}
JIT 现在知道数组索引不能越界,因为边界检查已经完成。因此它可以在生成的机器代码中省略正常的数组边界检查。
但如果您使用该字段,则它可能无法做出该假设。为什么,我不确定,但可能是因为跨线程问题。