数组索引器签名 returns 对象 - 它是否装箱?

Array indexer signature returns object - does it box?

我偶然发现 fact 索引器 this[int index] { get; } 对结构数组的工作方式与对结构列表的工作方式不同。也就是说,在 T[] return 的情况下,索引器是对数组中元素的引用,而在 List<T> return 的情况下,索引器是对数组中元素的一个副本元素.

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

但是,我对实际执行感到困惑。 .net 参考源中 Arraycode 如下所示:

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);
}

索引器的return类型是Object,表示会进行装箱。

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

我假设编译器 and/or CLR 会专门处理 Array,实际上不会理会索引器的签名。这个对吗?在某个地方有更全面的讨论吗?

Namely, that the indexer in the case of an T[] returns a reference to the element within the array

不是真的。更重要的是没有数组的索引器——取而代之的是 element-access 表达式表示数组访问而不是元素访问(C# 5 的第 7.6.6.1 和 7.6.6.2 节)规格)。

这两者之间存在非常显着的差异 - 特别是,数组访问被归类为 变量 ,而索引器访问被归类为 .

这与 属性 和字段之间的区别非常相似 - 它们都具有相同的访问语法,但是 属性 调用函数成员而 returns 一个值,而字段访问只会产生变量。

So my question is, can I be certain that no boxing will occur when I access an element of a T[] where T is a struct?

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

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

然后是的,这将把值装箱...但是如果你写

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

那么就不会了,它根本不会访问该索引器代码或 GetValue 方法。