数组索引器签名返回对象-是否返回框
本文关键字:返回 对象 是否 索引 数组 | 更新日期: 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
方法。