2

If I have an array property

private byte[] myProperty;

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

I can call it

MyProperty[3]

I would like to get index value 3 in getter. Is it possible to get index from array type property inside own getter like this

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

without using your own type like in this question and without changing property to method like this

public byte[] MyPropertyMethod(int index) => MyMethod(index);
ElConrado
  • 1,477
  • 4
  • 20
  • 46
  • You don´t need this. When your property is an array, it has the index-access anyway. Why would you want to re-invent it? Why would you want to do this? You can simply call `instance.MyProperty[3]` – MakePeaceGreatAgain Sep 12 '18 at 10:47
  • To have some comparison, you are looking for something like indexer properties in Delphi or [Oxygene](https://docs.elementscompiler.com/Oxygene/Members/Properties/), right? – O. R. Mapper Sep 12 '18 at 10:47
  • @HimBromBeere: The indexer of the array has read-write access and directly reads from/writes to the array (well, obviously). That may not be what is desired. – O. R. Mapper Sep 12 '18 at 10:49
  • If you are using an index-based getter, you do not return an array of bytes anymore, but a single byte. You can easily implement an indexer on your own type that will reflect the indexer of the array. – Zohar Peled Sep 12 '18 at 10:51
  • @O.R.Mapper yes it could be something similar – ElConrado Sep 12 '18 at 11:02
  • Honestly I don't think its feasable. Also the return type of `MyProperty` is `byte[]`. What would be the return type of your `MyMethod(index)`? It must be an byte array, but an indexer would return a `byte`. – ChristianMurschall Sep 12 '18 at 11:03
  • @O.R.Mapper If one wants a read-only array one could just define the property type as `IReadOnlyCollection` instead of `byte[]`. – ckuri Sep 12 '18 at 11:04
  • @ckuri: Which still allows (possibly undesired) casts to get to the inner object. I know there are various workarounds that make the resulting code look more or less the same, and based upon the final paragraph in the question, it seems the OP is well aware of them. – O. R. Mapper Sep 12 '18 at 11:06

1 Answers1

2

With restrictions you describe

without using your own type and without changing property to method

this is not possible (using C# language features).

The C# statement

byte i = MyProperty[3];

is compiled into following IL:

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

You see that the call to the property getter get_MyProperty (at offset IL_0020) occurs before the item index is even known. Only at offset IL_0025, the code knows that an array element at index 3 needs to be loaded from the array. At that time point, the getter method already returned, so you have no chance to get that index value anywhere inside of the method.

Your only option is a low-level IL code patching. You will need to "hack" the compiled IL code using third party tools or even manually, but both are strongly discouraged.

You will need to replace the calls to the getter method with direct calls to your 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
dymanoid
  • 14,771
  • 4
  • 36
  • 64