数组索引器签名返回对象-是否返回框

本文关键字:返回 对象 是否 索引 数组 | 更新日期: 2023-09-27 18:06:07

我偶然发现索引器this[int index] { get; }对结构体数组的工作方式与对结构体列表的工作方式不同。也就是说,对于T[],索引器返回对数组中元素的引用,而对于List<T>,索引器返回该元素的副本。

这是一个非常大的语义和性能差异,我很高兴T[]允许我们绕过List<T>的性能限制。

然而,我对实际的实现感到困惑。.net参考源代码中Array的代码如下:

Object IList.this[int index] {
    get { return GetValue(index); }
    set { SetValue(value, index); }
}

其中GetValue定义如下:

public unsafe Object GetValue(int index)
{
    if (Rank != 1)
       throw new ArgumentException(Environment.GetResourceString("Arg_Need1DArray"));
    Contract.EndContractBlock();
    TypedReference elemref = new TypedReference();
    InternalGetReference(&elemref, 1, &index);
    return TypedReference.InternalToObject(&elemref);
}

索引器的返回类型是Object,这意味着将进行装箱。

所以我的问题是,当我访问T[]的元素时,T是一个结构体,我能确定不会发生装箱吗?

我假设编译器和/或CLR对Array进行了特殊处理,实际上并不关心索引器的签名。这是正确的吗?有没有更详细的讨论?

数组索引器签名返回对象-是否返回框

也就是说,在T[]的情况下,索引器返回对数组

中的元素的引用

没有。更重要的是数组没有索引器——相反,元素访问表达式表示数组访问而不是元素访问(分别是c# 5规范的7.6.6.1和7.6.6.2节)。

这两者之间有非常显著的区别——特别是,数组访问被分类为变量,而索引器访问被分类为

这与属性和字段之间的区别非常相似——它们都具有相同的访问语法,但属性调用函数成员并返回值,而字段访问仅产生变量。

所以我的问题是,当我访问T[]其中T是一个结构体的元素时,我可以确定没有装箱会发生吗?

如果你访问它作为一个T[],当然。您查看的索引器仅在将数组视为IList时使用。所以如果你使用:

IList array = new int[2];
object x = array[0];

然后,是的,这将框值…但是如果你写

int[] array = new int[2];
int x = array[0];

那么它不会,它不会访问索引代码或GetValue方法。