2009-11-23 15 views
21

Quiero llamar a una función, con los parámetros a string y Int32. El string es solo un literal, el Int32 debe ser un field. Así que pensé que debería ser algo así como:¿Por qué tengo que hacer ldarg.0 antes de llamar a un campo en MSIL?

.method public hidebysig instance string TestVoid() cil managed 
{ 
    .maxstack 1 
    .locals init (
     [0] string CS$1$0000) 
    L_0000: nop 
    L_0001: ldstr "myString" 
    L_0006: ldfld int32 FirstNamespace.FirstClass::ByteField 
    L_000b: call string [Class1]Class1.TestClass::Functie<int32>(string, int32) 
    L_0010: ret 
} 

Pero esto arroja el error de que este no es un código válido. Al agregar

ldarg.0 

antes ldfld funciona perfectamente bien. ¿Por qué es esto, y esto me va a meter en problemas cuando tenga más campos?

Respuesta

35

Los métodos de instancia tienen un parámetro implícito llamado "this". Se carga como el primer argumento de la pila, por lo que tienes ldarg.0 para "esto".

+0

no ldarg.0 corresponde al primer parámetro pasado a un método? –

+2

Como explica Joel Marcey, hay un primer parámetro implícito "esto". Algo así como cuando declaras un método de extensión e incluye un parámetro (targetType targetObject, ... que luego no tienes que hacer referencia. – Phil

+0

... ej. Puedes tener un método: public static char MyStringMethod (this String inputString, int index) {return inputString [index];} - cuando lo llama, el primer parámetro está implícito - var myCharacter = myString.MyStringMethod (5); - pero todavía se carga cuando se ejecuta el método. – Phil

Cuestiones relacionadas