Можно ли получить индекс из свойства типа массива в собственном геттере - PullRequest
0 голосов
/ 12 сентября 2018

Если у меня есть свойство массива

private byte[] myProperty;

public byte[] MyProperty
{
    get { return myProperty; }
    set { myProperty= value; }
}

, я могу назвать его

MyProperty[3]

Я бы хотел получить значение индекса 3 в геттере.Можно ли получить индекс из свойства типа массива в собственном геттере, как этот

public byte[] MyProperty[int index]
{
    get 
    {
        return MyMethod(index);
    }
}

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

public byte[] MyPropertyMethod(int index) => MyMethod(index);

1 Ответ

0 голосов
/ 04 октября 2018

С ограничениями вы описываете

без использования своего собственного типа и без изменения свойства на метод

это невозможно (с использованием возможностей языка C #).

Оператор C #

byte i = MyProperty[3];

компилируется в следующий IL:

IL_001f: ldloc.0
IL_0020: callvirt instance uint8[] ConsoleApp1.Cls::get_MyProperty()
IL_0025: ldc.i4.3
IL_0026: ldelem.u1

Вы видите, что происходит вызов свойства getter get_MyProperty (со смещением IL_0020)до того, как предметный индекс станет известен.Только со смещением IL_0025 код знает, что элемент массива с индексом 3 должен быть загружен из массива.На тот момент метод getter уже возвращался, поэтому у вас нет шансов получить это значение индекса где-либо внутри метода.

Единственный вариант - низкоуровневое исправление кода IL.Вам нужно будет «взломать» скомпилированный код IL с помощью сторонних инструментов или даже вручную, но оба настоятельно не рекомендуется.

Вам нужно будет заменить вызовы метода get на прямые вызовы вашего MyMethod:

IL_001f: ldloc.0   // unchanged
                   // method call at IL_0020 removed
         ldc.i4.3  // instead, we first copy the index value from what was previously at IL_0025...
         callvirt instance uint8[] ConsoleApp1.Cls::MyMethod(int32) // ...and then call our own method
         ldc.i4.3  // the rest is unchanged
         ldelem.u1
...