Где я могу найти информацию о методах Get, Set и Address для многомерных экземпляров System.Array в .NET?

System.Array служит базовым классом для всех массивов в Общеязыковая среда выполнения (CLR). Согласно этой статье< /а>:

Для каждого конкретного типа массива среда выполнения добавляет три специальных метода: Get/Set/Address.

и действительно, если я разберу этот код C#,

int[,] x = new int[1024,1024];
x[0,0] = 1;
x[1,1] = 2;
x[2,2] = 3;
Console.WriteLine(x[0,0]);
Console.WriteLine(x[1,1]);
Console.WriteLine(x[2,2]);

в CIL я получаю,

IL_0000:  ldc.i4     0x400
IL_0005:  ldc.i4     0x400
IL_000a:  newobj     instance void int32[0...,0...]::.ctor(int32,
                                                         int32)
IL_000f:  stloc.0
IL_0010:  ldloc.0
IL_0011:  ldc.i4.0
IL_0012:  ldc.i4.0
IL_0013:  ldc.i4.1
IL_0014:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_0019:  ldloc.0
IL_001a:  ldc.i4.1
IL_001b:  ldc.i4.1
IL_001c:  ldc.i4.2
IL_001d:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_0022:  ldloc.0
IL_0023:  ldc.i4.2
IL_0024:  ldc.i4.2
IL_0025:  ldc.i4.3
IL_0026:  call       instance void int32[0...,0...]::Set(int32,
                                                       int32,
                                                       int32)
IL_002b:  ldloc.0
IL_002c:  ldc.i4.0
IL_002d:  ldc.i4.0
IL_002e:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_0033:  call       void [mscorlib]System.Console::WriteLine(int32)
IL_0038:  ldloc.0
IL_0039:  ldc.i4.1
IL_003a:  ldc.i4.1
IL_003b:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_0040:  call       void [mscorlib]System.Console::WriteLine(int32)
IL_0045:  ldloc.0
IL_0046:  ldc.i4.2
IL_0047:  ldc.i4.2
IL_0048:  call       instance int32 int32[0...,0...]::Get(int32,
                                                        int32)
IL_004d:  call       void [mscorlib]System.Console::WriteLine(int32)

где отчетливо видны вызовы вышеупомянутых методов Get и Set. Кажется, что арность этих методов связана с размерностью массива, поэтому, предположительно, они создаются средой выполнения, а не объявляются заранее. Я не смог найти информацию об этих методах в MSDN, а их простые названия делают их устойчивыми к поиску в Google. Я пишу компилятор для языка, который поддерживает многомерные массивы, поэтому я хотел бы найти официальную документацию об этих методах, при каких условиях я могу ожидать их существования и какие я могу ожидать их подписи.

В частности, я хотел бы знать, возможно ли получить объект MethodInfo для Get или Set для использования с Reflection.Emit без необходимости создания экземпляра массива с правильным типом и размерностью, на которых следует отражать , как это сделано в связанном примере.


person Rob Smallshire    schedule 31.03.2010    source источник
comment
@Rob: у тебя есть пример метода Address? А у вас есть ссылка с описанием того, что эти методы генерируются?   -  person John Saunders    schedule 31.03.2010
comment
@John - если вы нажмете ссылку «эта статья» в моем первом абзаце, вы попадете в статью, из которой взята цитата во втором абзаце.   -  person Rob Smallshire    schedule 31.03.2010


Ответы (3)


Посмотрите здесь, в частности, раздел 14.2 на страницах 63-65.

http://download.microsoft.com/download/7/3/3/733AD403-90B2-4064-A81E-01035A7FE13C/MS%20Partition%20II.pdf

Но вывод, как вы можете понять из IL, заключается в том, что они являются методами получения и установки для работы с массивами в заданных позициях индекса.

• Метод Get, который принимает последовательность аргументов типа int32, по одному для каждого измерения массива, и возвращает значение, тип которого является типом элемента массива. Этот метод используется для доступа к определенному элементу массива, где аргументы задают индекс в каждом измерении, начиная с первого, возвращаемого элемента.

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

• Метод Address, который принимает последовательность аргументов типа int32, по одному для каждого измерения массива, и имеет тип возвращаемого значения, являющийся управляемым указателем на тип элемента массива. Этот метод используется для возврата управляемого указателя на определенный элемент массива, где аргументы задают индекс в каждом измерении, начиная с первого, элемента, адрес которого должен быть возвращен.

Изменить: это страницы 63–65 с использованием нумерации страниц документа. 73-75 в фактическом PDF.

person Anthony Pegram    schedule 31.03.2010
comment
Превосходно! Это именно то, что я искал. Спасибо. - person Rob Smallshire; 01.04.2010

Чтобы ответить на ваш второй вопрос, вам не нужно создавать экземпляр, чтобы получить MethodInfo для этих методов. Что-то типа

var mi = typeof(string).MakeArrayType(6).GetMethod("Get");

будет работать, чтобы получить метод Get для типа string[,,,,,].

person kvb    schedule 31.03.2010
comment
Великолепный! Теперь у меня есть все, за чем я пришел. - person Rob Smallshire; 01.04.2010
comment
Впоследствии я обнаружил, что при выборе между перегрузками MakeArrayType требуется осторожность. Без аргументов — MakeArrayType() создает векторный тип, такой как string[]. С аргументом один - MakeArrayType(1) создает многомерный массив с одним измерением типа string[*]. Эти типы несовместимы. Для взаимодействия с другими языками .NET это означает, что, когда rank == 1, вам нужно будет указать особый случай вызова метода без параметров. - person Rob Smallshire; 03.04.2010

Я не уверен, что это ответит на ваш конкретный вопрос, но отличный текст на эту тему (среди прочего) CLR через C#. Он становится очень глубоким для многих тем, которые вас интересуют, и проводит много времени с дизассемблером, изучающим внутреннюю работу многих базовых типов .NET, включая массивы. Определенно стоит проверить.

person Paul Sasik    schedule 31.03.2010
comment
Спасибо, что напомнили мне взглянуть на CLR через C#, который у меня есть. Я только что прочитал главу 13: Массивы, но не нашел упоминания о методах Get, Set и Address. - person Rob Smallshire; 31.03.2010