Behind the Scenes Look at C#: Indexers - A Look at the MSIL Code
(Page 4 of 4 )
Load the application with the Ildasm.exe tool and expand the Department and the Class1 classes. You will get the following figure:

As we have said, the indexer is implemented down to the MSIL code as a default property called "item," and it creates get_Item method and set_Item method in much the same way that any property does. Double click on the Item property and you will get the following MSIL code:
.property instance class indexers.Employee
Item(int32)
{
.get instance class indexers.Employee indexers.Department::get_Item(int32)
.set instance void indexers.Department::set_Item(int32,
class indexers.Employee)
} // end of property Department::Item
As you can see, it's a property declaration that contains the get and set method declarations too. Double click on the get_Item method to get to the following MSIL code:
.method public hidebysig specialname instance class indexers.Employee
get_Item(int32 arg) cil managed
{
// Code size 13 (0xd)
.maxstack 2
.locals init ([0] class indexers.Employee CS$00000003$00000000)
IL_0000: ldarg.0
IL_0001: ldfld class indexers.Employee[] indexers.Department::Employees
IL_0006: ldarg.1
IL_0007: ldelem.ref
IL_0008: stloc.0
IL_0009: br.s IL_000b
IL_000b: ldloc.0
IL_000c: ret
} // end of method Department::get_Item
This is much the same as the code of any other get accessor method. The one thing that you should note is that the method contains a new instruction, which is the ldelem.ref instruction. This stands for "load element reference," and it does what its name says. This is an element loading instruction; it takes the element index and an object reference of the Stack and then puts the value of the element on the stack. The ref part of the instruction means that it will load an object reference. Note that the get method takes a parameter of type int32 as you can see in the MSIL code. Double click on the method set_Item to get to the following code:
.method public hidebysig specialname instance void
set_Item(int32 arg,
class indexers.Employee 'value') cil managed
{
// Code size 10 (0xa)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldfld class indexers.Employee[] indexers.Department::Employees
IL_0006: ldarg.1
IL_0007: ldarg.2
IL_0008: stelem.ref
IL_0009: ret
} // end of method Department::set_Item
The only new instruction is the stelem.ref instruction, which stands for "Store Element Reference." This is called an element storing instruction. It takes the value and the object reference and stores them, and it doesn't put anything on the Stack. Note that the set_Item accessor method takes two parameters (not one as in our ordinary properties); the first is the index and the second is the parameter value (of type Employee). It's something like stating where you want store this object reference. Load the Main method, and I'm sure that the code will not come as a surprise for you. I will copy just a snippet of the code here.
IL_00da: ldloc.0
IL_00db: ldc.i4.3
IL_00dc: ldloc.s emp4
IL_00de: callvirt instance void indexers.Department::set_Item(int32,
class indexers.Employee)
IL_00e3: ldloc.0
IL_00e4: ldc.i4.4
IL_00e5: ldloc.s emp5
IL_00e7: callvirt instance void indexers.Department::set_Item(int32,
class indexers.Employee)
IL_00ec: ldloc.0
IL_00ed: ldc.i4.5
IL_00ee: ldloc.s emp6
IL_00f0: callvirt instance void indexers.Department::set_Item(int32,
class indexers.Employee)
All I want to mention about this code is the set_Item method of each object. Simply, this code loads the object onto the Stack and then assigns it to the internal array object using the indexer property's method set_Item and, as we just said, this method takes two parameters (the value of the array index and the object reference it will stores). In the second part of this tutorial we will extend the example to include the Department's class, add another indexer to this class, and then replace all the indexers with an advanced array object.
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |