2016-09-07 4 views
5

Я наткнулся на fact, что индекс this[int index] { get; } работает по-разному для массива структур, чем для списка структур. А именно, что индексщик в случае T[] возвращает ссылку на элемент внутри массива, тогда как индексщик в случае List<T> возвращает копию элемента.Атрибут индекса индекса массива возвращает объект - это поле?

Это очень большая семантика и разница в производительности, и я рад, что T[] позволяет нам обойти ограничение производительности List<T>.

Однако, я озадачен фактической реализацией. code для Array в справочных источниках .net звучит так:

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 относятся к массиву специально и на самом деле не беспокоят подпись индексатора. Это верно? Есть ли более полное обсуждение этого?

+0

'IList.SomeMethod' - это реализация [implicit intefrace] (http://stackoverflow.com/q/143405/1997232). Это способ сказать * «этот метод существует, если объект классифицируется как« IList »*. Он будет использоваться только в том случае, если вы специально запросите его, например. в случае индексатора '((IList) someArray) [x]'. Другое обращение к индексу индекса массива (например, 'someArray [x]') - другое дело, вы не найдете источников для какого-либо метода, потому что их нет. – Sinatr

ответ

9

А именно, что индексатор в случае T [] возвращает ссылку на элемент в массиве

Не совсем. Более того, нет индексатора для массивов - вместо выражения элемент-доступ представляет собой доступ к массиву вместо доступа к элементу (разделы 7.6.6.1 и 7.6.6.2 спецификации C# 5 соответственно).

Там очень существенное различие между этими двумя - в частности, доступ к массиву классифицируется как переменной, в то время как доступ индексатор классифицируется как значение.

Это очень похоже на разницу между свойством и полем - оба они имеют одинаковый синтаксис для доступа, но свойство вызывает элемент функции и возвращает значение, тогда как доступ к полю просто дает переменную.

Так что мой вопрос, могу ли я быть уверен, что ни один бокс не будет происходить, когда я получить доступ к элементу в T[] где T является структура?

Если вы обращаетесь это , какT[], конечно. Указатель, на который вы смотрели, используется только тогда, когда вы просматриваете массив как IList. Поэтому, если вы используете:

то да, это будет полезна ...но если вы пишете

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

то, что не будет, и это не будет доступ к этому коду индексатора или GetValue метод вообще.

+0

Другой способ взглянуть на это: 'System.Array' похож на базовый тип всех массивов. Реализация 'IList.this [int index]' в этом базовом типе существует, поэтому массивы будут реализовывать 'System.Collections.IList', а не для регулярного доступа к элементам. –

+0

Отлично, спасибо. Следующий вопрос - есть ли что-нибудь в Array.cs, которое выполняется, когда я вызываю массив [index]? Или это все реализовано непосредственно CLR? – bright

+1

@bright: Все в CLR, насколько мне известно. Там IL специально для доступа к массиву, хотя я не могу вспомнить имена op. –

 Смежные вопросы

  • Нет связанных вопросов^_^