我应该怎么做"可能比较值类型与'null'"?

Gro*_*ile 71 c#

在为自定义NUnit约束编写此方法时.

    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()));
    }
Run Code Online (Sandbox Code Playgroud)

Resharper警告expectedactual可能是ValueType物体.

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

将ValueType与null进行比较时有哪些规则?如何在不限制通用参数的情况下通过添加类约束来编写方法来解决这个问题?

Jon*_*eet 80

不要更改代码 - 只需忽略警告.如果type参数是非可空值类型,则比较将始终失败,并且它将始终调用ToString().我不知道它是否实际上是JITted,但我不会感到惊讶......这听起来不像是性能关键代码:)

我个人将警告"打开",但在这种特殊情况下忽略它 - 可能有评论.

当我重新实现LINQ to Objects时,我想我几次遇到同样的警告.

  • 当然,"//我有Skeet先生(TODO在这里添加撇号)明确许可忽略这个警告." (64认同)
  • 我添加了"//我有Skeets先生明确允许忽略此警告." 似乎做的伎俩:) (61认同)
  • @panamack:我可以在"Skeet's"中请求撇号吗?助教. (17认同)
  • 值得注意的是,如果某人真的被错误消息困扰,他们总是可以做`Object.ReferenceEquals(objA,null)`这实际上只是在.NET源代码中调用`objA == objB`.而且,我很确定这将是JITted或以某种方式内联.好消息是,错误消息消失了,并且调用仍然有效:) (15认同)
  • 为了完整起见,Eric Lippert [说](http://stackoverflow.com/a/8824259/1083771)在编译类型参数的方法时,JIT实际上用"false"替换了"val == null"检查这是一个不可为空的值类型. (4认同)

jas*_*son 6

将ValueType与null进行比较时有哪些规则?如何在不限制通用参数的情况下通过添加类约束来编写方法来解决这个问题?

如果您不知道它们将是引用类型,那么您可以说

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";
    }
}
Run Code Online (Sandbox Code Playgroud)