I stumbled on the fact that the indexer this[int index] { get; }
works differently for an array of structs than it does for a List of structs. Namely, that the indexer in the case of an T[]
returns a reference to the element within the array whereas the indexer in the case of a List<T>
returns a copy of the element.
This is a very big semantic and performance difference, and I'm glad that T[]
allows us to work around the performance limitation of List<T>
.
However, I'm puzzled by the actual implementation. The code for Array
in the .net reference sources reads thus:
Object IList.this[int index] {
get { return GetValue(index); }
set { SetValue(value, index); }
}
Where GetValue
is defined as follows:
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);
}
The return type of the indexer is Object
, implying that boxing will take place.
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?
I assume that the compiler and/or CLR treat Array specially, and don't actually bother with the signature of the indexer. Is this correct? Is there a fuller discussion of this somewhere?
IList.SomeMethod
is an implicit intefrace implementation. It's a way of telling "this method exists if object is classified asIList
". It will only be used if you specifically request it, e.g. in case of indexer((IList)someArray)[x]
. Accessing array indexer directly (e.g.someArray[x]
) is another thing, you won't find sources for any method because there is none. – Exhortative