Today I am reading C # GenericCodeI hope you will not be tired of talking about generics.
Yes, or the two classes I wrote last time:
Interface itest
{
Void testmethod ();
}
Class test <t> where T: itest, new ()
{
Public test ()
{
T = new T ();
}
Public void Foo ()
{
T. testmethod ();
}
Private t;
}
When observing the Il code of the test <t>. Foo () function, a suspicious box operation is found:
. Method public hidebysig instance void Foo () cel managed
{
// Code size 17 (0x11)
. Maxstack 8
Il_0000: ldarg.0
Il_0001: ldquo! 0 class consoleapplication1.test <! 0>: T
Il_0006: box! 0
Il_000b: callvirt instance void consoleapplication1.itest: testmethod ()
Il_0010: Ret
} // End of method test: foo
The consoleapplication is namespace ,! 0 is a placeholder for the generic parameter t in Il.
From the code above, the instance test <t>: t of the generic parameter is treated as a valuetype, and is called as an interface defined in constraint when calling the relevant method, then callvirt is used to call the virtual function of the interface. As a result, box and transformation seem to increase the overhead of calling methods.
Write a multi-state version that implements the same function for comparison:
Class testvirtual
{
Public static void Foo (itest I)
{
I. testmethod ();
}
}
The IL code generated by the corresponding Foo function is as follows:
. Method public hidebysig static void Foo (class consoleapplication1.itest I) cel managed
{
// Code size 7 (0x7)
. Maxstack 8
Il_0000: ldarg.0
Il_0001: callvirt instance void consoleapplication1.itest: testmethod ()
Il_0006: Ret
} // End of method testvirtual: foo
Obviously, the cost is much lower.
If you change the above generic il code:
. Method public hidebysig instance void Foo () cel managed
{
// Code size 17 (0x11)
. Maxstack 8
Il_0000: ldarg.0
Il_0001: ldquo! 0 class consoleapplication1.test <! 0>: T
Il_0006: box! 0
Il_000b: Call instance void! 0: testmethod ()
Il_0010: Ret
} // End of method test: foo
The system. missingmethodexception is generated, and the prompt message is as follows:
Unhandled exception: system. missingmethodexception: method not found: 'void system. Object. testmethod ()'.
From this, we can see that the instance of the generic parameter is converted into an object instance by box, which is consistent with the implicit generic parameter inherited from the object's constraints. It seems that CLR generic support is at best some underlying transformation actions, and the overhead of a box does not know who is more overhead than Java's generic support.
Finally, let's talk about some other things. ninputer complained that valuetype or referencetype could not be restricted. He thought that he had seen this in the C # team blog last time. He was indeed ready to add this function. Here!