Подтвердить что ты не робот

Что мне делать в отношении "Возможное сравнение типа значения с" null "?

При написании этого метода для пользовательской NUnit Constraint.

    private void AddMatchFailure<TExpected, TActual>(string failureName, TExpected expected, TActual actual)
    {
        _matchFailures.Add(
            String.Format(MatchFailureFormat, failureName,
            (expected == null) ? "null" : expected.ToString(),
            (actual == null) ? "null" : actual.ToString()));
    }

Resharper предупреждает, что expected и actual могут быть ValueType объектами.

e.g. TExpected is DateTime
   expected == null;//  but DateTime is a struct.

Каковы правила при сравнении значения ValueType с нулем и как я должен писать метод для учета этого, не ограничивая общие параметры, добавляя ограничение класса?

4b9b3361

Ответ 1

Не меняйте код - просто игнорируйте предупреждение. Если параметр типа является типом значения, отличным от NULL, сравнение всегда будет терпеть неудачу, и он всегда будет называть ToString(). Я не знаю, действительно ли это произошло, но я не удивлюсь... и это не похоже на критически важный для работы код:)

Я лично оставил бы предупреждение "on", но проигнорировал его в этом конкретном случае - возможно, с комментарием.

Я думаю, что несколько раз сталкивался с тем же предупреждением, когда переопределял LINQ to Objects.

Ответ 2

Каковы правила при сравнении значения ValueType с нулем и как я должен писать метод для учета этого, не ограничивая общие параметры, добавляя ограничение класса?

Если вы не знаете, что они будут ссылочными типами, вы можете сказать

private void AddMatchFailure<TExpected, TActual>(
    string failureName,
    TExpected expected,
    TActual actual
) {
    _matchFailures.Add(
        String.Format(MatchFailureFormat, failureName,
        IsDefault<TExpected>(expected) ? DefaultStringForType<TExpected>() : expected.ToString(),
        IsDefault<TActual>(actual) ? DefaultStringForType<TActual>() : actual.ToString()
    );
}

private bool IsDefault<T>(T value) {
    if(typeof(T).IsValueType) {
        return default(T).Equals(value);
    }
    else {
        return Object.Equals(null, value);
    }
}

private string DefaultStringForType<T>() {
    if(typeof(T).IsValueType) {
        return default(T).ToString();
    }
    else {
        return "null";
    }
}

Ответ 3

Я использую что-то вроде этого, чтобы проверить значение null на общих типах:

if (Equals(result, Default(T)))

Ответ 4

private void AddMatchFailure<TExpected, TActual>(string failureName, TExpected expected, TActual actual)
{
    _matchFailures.Add(
        String.Format(MatchFailureFormat, failureName,
        (expected == default(TExpected)) ? "null" : expected.ToString(),
        (actual == default(TActual)) ? "null" : actual.ToString()));
}

Должно это сделать.

default(T) дает значение по умолчанию для этого типа, для ссылочных типов это значение null - для других это зависит. (Предположим, что это эквивалент (enumType)0).