2014-12-18 9 views
1

Индексирование массива, независимо от его размеров, является вызовом метода, поскольку он включает вызов оператора индексатора .Почему экземпляр индексации одномерного массива представляет собой двоичное выражение, а не выражение MethodCallExpression?

Тогда почему перегрузка метода System.Linq.Expressions.Expression.ArrayIndextakes a single array index, что сделано, чтобы возвращать BinaryExpression тогда как его other overloads, которые представляют собой индексы многомерные массивы, сделаны для возврата MethodCallExpression S?

Это просто нарушает симметрию, заставляя меня помнить эту маленькую аномалию. Если бы они сделали это MethodCallExpression, мне бы не пришлось помнить или ничего не учитывать.

+1

Хмм-индекс индекса как вызов метода в ИЛ? Это приведет к тому, что массив будет работать в два раза медленнее, я не вижу причин для этого. Одномерные массивы настроены на производительность. Многомерных массивов нет. –

+0

Спасибо. Я не настолько образован в отношении ИЛ. Это один из этих элементов в моем списке дел. –

ответ

3

Я подозреваю, что это потому, что это похоже на IL. CLI имеет два разных типа массивов: векторы, которые представляют собой массивы с рангом 1, 0 нижней границей, и массивы, которые являются массивами «любого ранга, любой нижней границы». (Да, именование очень запутанно. Извините.)

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

Чтобы продемонстрировать это, скомпилировать этот код:

class Test 
{ 
    static void Main() 
    { 
     int[] vector = new int[10]; 
     int[,] array = new int[10, 10]; 
     int x = vector[0]; 
     int y = array[0, 0]; 
    } 
} 

Тогда смотреть на него с ILDASM - последние две строки метода компилируются как:

// int x = vector[0] 
IL_0013: ldloc.0 
IL_0014: ldc.i4.0 
IL_0015: ldelem.i4 
IL_0016: stloc.2 

// int y = array[0, 0] 
IL_0017: ldloc.1 
IL_0018: ldc.i4.0 
IL_0019: ldc.i4.0 
IL_001a: call  instance int32 int32[0...,0...]::Get(int32, 
                  int32) 
IL_001f: stloc.3 

Поэтому выражение дерево просто представляя инструкцию ldelem как двоичный оператор (где два операнда являются предположительно массивом и индексом), тогда как он использует вызов метода для многомерного массива.

+0

спасибо. :-) –

+0

Не должен ли сегмент IL для 'vector' включать инструкцию' IL_0013: ldloc.0'? – svick

+0

@svick: Возможно, будет исправлено это через минуту. –