Если вы используете ILDasm, вы можете получить хорошую разбивку методов, перейдите в View -> Meta Info -> select More Hex. Затем перейдите в View -> Meta Info -> Show!
Вот разбивка для второго метода:
Method #2 (06000002)
-------------------------------------------------------
MethodName: GenericMethod (06000002)
Flags : [Public] [HideBySig] [ReuseSlot] (00000086)
RVA : 0x0000206c
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
generic
Type Arity:1
ReturnType: String
2 Arguments
Argument #1: Var!0
Argument #2: MVar!!0
Signature : 30 01 02 0e 13 00 1e 00
1 Generic Parameters
(0) GenericParamToken : (2a000003) Name : N flags: 00000000 Owner: 06000002
2 Parameters
(1) ParamToken : (08000002) Name : anItem flags: [none] (00000000)
(2) ParamToken : (08000003) Name : secondItem flags: [none] (00000000)
Если прокрутить вниз, вы также увидите записи таблицы TypeSpec.
TypeSpec # 1 (1b000001)
TypeSpec : MVar!!0
Signature: 1e 00
TypeSpec # 2 (1b000002)
TypeSpec : Var!0
Signature: 13 00
То, что ILdasm показывает выше, это то, что VAR (13 00) является универсальным! T, передаваемым на уровне класса (универсальный параметр в определении типа), а MVAR (1e 00) является универсальным !! N, передаваемым на уровне метода ( универсальный параметр в определении метода).
Однако ... вы уже знаете, что у Ориона есть ваш ответ - записи в таблице TypeSpec используются в IL. Одна запись используется в одном методе, а другая - в другом методе. Вы можете увидеть это в ILdasm, когда посмотрите на методы:
.method /*06000001*/ public hidebysig instance void
'GenericMethod'<'N'>(!!'N' 'anItem') cil managed
// SIG: 30 01 01 01 1E 00
{
// Method begins at RVA 0x2050
// Code size 16 (0x10)
.maxstack 1
.locals /*11000001*/ init ([0] string 's')
IL_0000: /* 00 | */ nop
IL_0001: /* 0F | 01 */ ldarga.s 'anItem'
IL_0003: /* FE16 | (1B)000001 */ constrained. !!'N'/*1B000001*/
IL_0009: /* 6F | (0A)000011 */ callvirt instance string ['mscorlib'/*23000001*/]'System'.'Object'/*01000001*/::'ToString'() /* 0A000011 */
IL_000e: /* 0A | */ stloc.0
IL_000f: /* 2A | */ ret
} // end of method 'AllOutputTypesClass`1'::'GenericMethod'
и
.method /*06000002*/ public hidebysig instance string
'GenericMethod'<'N'>(!'T' 'anItem',
!!'N' 'secondItem') cil managed
// SIG: 30 01 02 0E 13 00 1E 00
{
// Method begins at RVA 0x206c
// Code size 19 (0x13)
.maxstack 1
.locals /*11000001*/ init ([0] string 'CS$1$0000')
IL_0000: /* 00 | */ nop
IL_0001: /* 0F | 01 */ ldarga.s 'anItem'
IL_0003: /* FE16 | (1B)000002 */ constrained. !'T'/*1B000002*/
IL_0009: /* 6F | (0A)000011 */ callvirt instance string ['mscorlib'/*23000001*/]'System'.'Object'/*01000001*/::'ToString'() /* 0A000011 */
IL_000e: /* 0A | */ stloc.0
IL_000f: /* 2B | 00 */ br.s IL_0011
IL_0011: /* 06 | */ ldloc.0
IL_0012: /* 2A | */ ret
} // end of method 'AllOutputTypesClass`1'::'GenericMethod'
Таблица 0x1b - это TypeSpec, поэтому в следующих строках из вышеприведенных методов показано использование двух строк, которые вас интересуют:
IL_0003: /* FE16 | (1B)000001 */ constrained. !!'N'/*1B000001*/
и
IL_0003: /* FE16 | (1B)000002 */ constrained. !'T'/*1B000002*/