Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the generic type looks like (!!T) at function definition in CIL

Tags:

c#

generics

cil

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)
like image 460
r00tdev Avatar asked Mar 15 '23 13:03

r00tdev


1 Answers

!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).

like image 72
SLaks Avatar answered Apr 26 '23 13:04

SLaks