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
ExplicitThis
is set,HasThis
must also be set. The first argument passed to the called method is still athis
pointer, but the type of the first argument is now unknown. Therefore, a token that describes the type (or class) of thethis
pointer 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
this
pointer). 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