dotnet集合源代码中内部数组的局部变量副本的目的是什么

问题描述 投票:0回答:1

作为 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
来代替呢?

我在谷歌中找不到任何线索,所以期待在这里得到一些见解。

c# .net collections variable-assignment implementation
1个回答
-1
投票

我不能肯定地说,但我希望这将是某种 JIT 优化。

猜测:虽然 JIT 确实有逻辑来进行边界检查省略,但如果您两次引用该字段而不是局部变量,它可能不起作用。

函数

ThrowForEmptyStack
已知是无返回的:

private void ThrowForEmptyStack()
{
    Debug.Assert(_size == 0);
    throw new InvalidOperationException(SR.InvalidOperation_EmptyStack);
}

所以当代码进行检查时

if ((uint)size >= (uint)array.Length)
{
    ThrowForEmptyStack();
}

JIT 现在知道数组索引不能越界,因为边界检查已经完成。因此它可以在生成的机器代码中省略正常的数组边界检查。

但如果您使用该字段,则它可能无法做出该假设。为什么,我不确定,但可能是因为跨线程问题。

© www.soinside.com 2019 - 2024. All rights reserved.