Что делает CLR, когда сравнивает T с нулем, а T является структурой? - PullRequest
8 голосов
/ 19 марта 2010
private static void SaveOrRemove<T>(string key, T value)
{
    if (value == null)
    {
        Console.WriteLine("Remove: " + key);
    }

    //...
}

Если я вызываю передачу 0 к значению: SaveOrRemove("MyKey", 0), условие value == null ложно, тогда CLR не делает value == default(T). Что на самом деле происходит?

Ответы [ 3 ]

10 голосов
/ 19 марта 2010

JIT-компилятор в основном удаляет любые сравнения со значением NULL, когда T является ненулевым типом значения, предполагая, что все они имеют значение false. (Типы значений Nullable будут сравниваться с нулевым значением для этого типа, что, вероятно, является тем, что вы ожидаете.)

Если вы хотите сравнить его со значением по умолчанию, вы можете использовать:

if (EqualityComparer<T>.Default.Equals(value, default(T))
{
    ...
}
5 голосов
/ 19 марта 2010

На ваш вопрос ответили в разделе 7.9.6 спецификации C #:

Если операнд типа параметра типа T сравнивается с нулем, а время выполнения тип T является типом значения, результат сравнения ложно.

0 голосов
/ 19 марта 2010

Если вы хотите default(T), вы должны сказать это, а не null, что имеет свое собственное значение. Если вы хотите, чтобы способность фактически передавала null вместо типа значения, вы должны использовать Nullable<T>.

Итак, ваш код станет:

private static void SaveOrRemove<T>(string key, Nullable<T> value)
{
    if (!value.HasValue()) // is null
    {
        Console.WriteLine("Remove: " + key);
    }
    else
    {
        T val = value.Value;
        // ...
    }
}

Обратите внимание, что Nullable<T> полезен только для типов значений (структуры, "встроенные", отличные от строки); для ссылочных типов вы все равно не сможете его использовать.

MSDN-ссылка

...