开发者

What should I do about "Possible compare of value type with 'null'"?

开发者 https://www.devze.com 2023-02-17 05:54 出处:网络
While writing this method for a custom NUnit Constraint. private void AddMatchFailure<TExpected, TActual>(string failureName, TExpected expected, TActual actual)

While writing this method for a custom 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 warns that expected and actual might be ValueType objects.

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

What are t开发者_如何学运维he rules when comparing a ValueType to null and how should I write the method to account for that without limiting the generic parameters by adding a class constraint?


Don't change the code - just ignore the warning. If the type parameter is a non-nullable value type, the comparison will always fail and it'll always call ToString() instead. I don't know whether it's actually JITted away, but I wouldn't be surprised... and this doesn't sound like it's performance-critical code anyway :)

I'd personally leave the warning "on", but ignore it in this particular case - possibly with a comment.

I think I came across the same warning a few times when reimplementing LINQ to Objects.


What are the rules when comparing a ValueType to null and how should I write the method to account for that without limiting the generic parameters by adding a class constraint?

If you do not know that they will be reference types, then you can say

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";
    }
}


I'm using something like this to check for null on generic types:

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


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()));
}

Should do it.

default(T) gives the default value for that type, for reference types that's null - for others it depends. (Enums it's the equivalent of (enumType)0 for example).

0

精彩评论

暂无评论...
验证码 换一张
取 消