Я столкнулся с очень забавной ситуацией, когда сравнение типа nullable с null внутри общего метода на 234x медленнее, чем сравнение типа значения или ссылочного типа. Код выглядит следующим образом:
static bool IsNull<T>(T instance)
{
return instance == null;
}
Код выполнения:
int? a = 0;
string b = "A";
int c = 0;
var watch = Stopwatch.StartNew();
for (int i = 0; i < 1000000; i++)
{
var r1 = IsNull(a);
}
Console.WriteLine(watch.Elapsed.ToString());
watch.Restart();
for (int i = 0; i < 1000000; i++)
{
var r2 = IsNull(b);
}
Console.WriteLine(watch.Elapsed.ToString());
watch.Restart();
for (int i = 0; i < 1000000; i++)
{
var r3 = IsNull(c);
}
watch.Stop();
Console.WriteLine(watch.Elapsed.ToString());
Console.ReadKey();
Вывод для кода выше:
00: 00: 00,1879827
00: 00: 00,0008779
00: 00: 00,0008532
Как вы можете видеть, сравнение значения nullable int в null равно 234x медленнее, чем сравнение int или строки. Если я добавлю вторую перегрузку с правильными ограничениями, результаты резко меняются:
static bool IsNull<T>(T? instance) where T : struct
{
return instance == null;
}
Теперь результаты:
00: 00: 00,0006040
00: 00: 00,0006017
00: 00: 00,0006014
Почему? Я не проверял байтовый код, потому что я не уверен в этом, но даже если бы байтовый код был немного другим, я бы ожидал, что JIT оптимизирует это, и это не (я работаю с оптимизацией).