对于“值类型与‘ null’的可能比较”,我应该做什么?

在为自定义 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()));
}

Resharper 警告说,expectedactual可能是 ValueType对象。

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

比较 ValueType 和 null 的规则是什么? 我应该如何编写方法来解释这一点,而不必通过添加类约束来限制泛型参数?

11672 次浏览
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)。

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

我个人会把警告“打开”,但在这个特殊的情况下忽略它——可能还会加上一条评论。

我想我在重新实现 LINQ to Objects 时遇到过几次同样的警告。

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

我使用类似的方法来检查泛型类型是否为 null:

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