Why is the generic type looks like (!!T) at function definition and (!!0) at caller in CIL. In some scenario, the parameter of generic type looks like (!0). What's the secret behind? or why is it design in such way?
Thank you in advance.
Below is the code in C#:
private static void Main(string[] args)
{
Test<int>();
TestList<int>(new List<int>{ 1, 2,3 }, 1, 2, 3, 4, 5, 6, 7,8);
Console.ReadKey();
}
private static void TestList<T>(List<T> list, T item, T t2, T t3, T t4, T t5, T t6, T t7, int t8)
{
Console.WriteLine(item == null);
Console.WriteLine("Collection contains {0}? {1}", item, list.Contains(item));
}
and the CIL code of Calling TestList:
IL_002e: call void BoxingAndUnboxing.Program::TestList<int32>(class [mscorlib]System.Collections.Generic.List`1<!!0>,
!!0,
!!0,
!!0,
!!0,
!!0,
!!0,
!!0,
int32)
and the CIL code of function definition:
.method private hidebysig static void TestList<T>(class [mscorlib]System.Collections.Generic.List`1<!!T> list,
!!T item,
!!T t2,
!!T t3,
!!T t4,
!!T t5,
!!T t6,
!!T t7,
int32 t8) cil managed
and the CIL code of showing type as !0 rather than !!0
IL_001d: callvirt instance bool class [mscorlib]System.Collections.Generic.List`1<!!T>::Contains(!0)
!0
means the first generic parameter of the containing class.!!0
means the first generic parameter of the method itself.
The method in class C<X> { void M<Y>(X a, Y b) {} }
would be referred to as C`1::M`1(!0, !!0)
. !0
is X
, and !!0
is Y
.
Finally, !!0
, used when referring to a method, means the first parameter declared by the method, whereas !!T
, used in actual implementation, means the type parameter of the current method that is named T
.
!!0
is necessary in method references to distinguish between M<X, Y>(X x, Y y)
and M<X, Y>(Y y, X x)
, which become M`2(!!0, !!1)
and M`2(!!1, !!0)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With