Я проанализировал код IL трех следующих методов:
generic<class T> where T : value class, System::ValueType
static void MyMethod(T arg)
{
}
generic<typename T> where T: value class
static void MyMethod2(T arg)
{
}
generic<typename T> where T: ValueType
static void MyMethod3(T arg)
{
}
Соответствующий IL-код, который я разбирал с помощью .NET-Reflector:
.method public hidebysig
static void MyMethod<valuetype ([mscorlib]System.ValueType).ctor T>
(!!T arg) cil managed
{
}
.method public hidebysig
static void MyMethod2<valuetype .ctor T>(!!T arg) cil managed
{
}
.method public hidebysig
static void MyMethod3<([mscorlib]System.ValueType) T>(!!T arg) cil managed
{
}
Это IL-декларация Nullable<T>
:
.class public sequential ansi serializable sealed beforefieldinit
Nullable<valuetype (System.ValueType) .ctor T>
extends System.ValueType
Как вы можете ясно видеть, только ограничение первого метода соответствует 100% с Nullable<T>
. (Кстати: value class
, кажется, подразумевает наличие стандартного конструктора). Однако, почему компилятор создает разные IL-коды для (семантически) одинаковых ограничений, остается загадкой. Я буду просить гуру Microsoft C ++ / CLI для получения дополнительной информации.