I come across HasThis and ExplicitThis calling conventions on .NET Framework reference source, and thus I begin to wonder:
- When are they set by compiler?
- Are there any examples using this combination of calling conventions (in "real world" managed program)?
MSDN has described them as:
ExplicitThis
Specifies that the signature is a function-pointer signature, representing a call to an instance or virtual method (not a static method). If
ExplicitThisis set,HasThismust also be set. The first argument passed to the called method is still athispointer, but the type of the first argument is now unknown. Therefore, a token that describes the type (or class) of thethispointer is explicitly stored into its metadata signature.
HasThis
Specifies an instance or virtual method (not a static method). At run-time, the called method is passed a pointer to the target object as its first argument (the
thispointer). The signature stored in metadata does not include the type of this first argument, because the method is known and its owner class can be discovered from metadata.
Here is a sample program I wrote to generate a class and constructor using these bits set:
const string FileName = "MyDynamicLib.dll";
AppDomain currentDomain = AppDomain.CurrentDomain;
AssemblyName assemblyName = new AssemblyName(assemblyName: "MyAssembly");
AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(
name : assemblyName,
access: AssemblyBuilderAccess.RunAndSave
);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(
name : "MyModule",
fileName : FileName,
emitSymbolInfo: true
);
TypeBuilder typeBuilder = moduleBuilder.DefineType(
name: "MyClass",
attr: TypeAttributes.Public | TypeAttributes.BeforeFieldInit
);
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
attributes : MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
callingConvention: CallingConventions.HasThis | CallingConventions.ExplicitThis,
parameterTypes : null
);
constructorBuilder.GetILGenerator().Emit(opcode: OpCodes.Ret);
typeBuilder.CreateType();
assemblyBuilder.Save(
assemblyFileName : FileName,
portableExecutableKind: PortableExecutableKinds.Required32Bit,
imageFileMachine : ImageFileMachine.I386
);
Aucun commentaire:
Enregistrer un commentaire