C# “我该怎么办?”;可能将值类型与';空'&引用;?
为自定义NUnit约束编写此方法时C# “我该怎么办?”;可能将值类型与';空'&引用;?,c#,C#,为自定义NUnit约束编写此方法时 private void AddMatchFailure<TExpected, TActual>(string failureName, TExpected expected, TActual actual) { _matchFailures.Add( String.Format(MatchFailureFormat, failureName, (expected ==
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()));
}
将ValueType与null进行比较时有哪些规则?我应该如何编写方法来说明这一点,而不通过添加类约束来限制泛型参数?private void AddMatchFailure(字符串failureName,预期的TExpected,实际的TActual)
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()));
}
{
_匹配失败。添加(
String.Format(匹配FailureFormat、failureName、,
(预期==默认值(TExpected))?“null”:预期为.ToString(),
(actual==default(TActual))?“null”:actual.ToString());
}
我应该这样做
default(T)
给出该类型的默认值,对于为null的引用类型,它取决于其他类型。(例如,它相当于(enumType)0
。不要更改代码,只需忽略警告即可。如果type参数是不可为null的值类型,则比较将始终失败,并始终调用ToString()
。我不知道这是否真的让人紧张,但我不会感到惊讶。。。而且这听起来并不像是性能关键的代码:)
我个人会让警告“开着”,但在这个特殊的情况下忽略它——可能会有评论
我想我在将LINQ重新实现到对象时遇到过几次相同的警告
将ValueType与null进行比较时有哪些规则?我应该如何编写方法来说明这一点,而不通过添加类约束来限制泛型参数
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()));
}
如果您不知道它们将是引用类型,那么您可以说
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";
}
}
private void AddMatchFailure(
字符串失败名称,
预期,
触觉实际
) {
_匹配失败。添加(
String.Format(匹配FailureFormat、failureName、,
IsDefault(应为)?DefaultStringForType():应为.ToString(),
IsDefault(实际值)?DefaultStringForType():实际值.ToString()
);
}
私有布尔值默认值(T值){
if(类型(T).IsValueType){
返回默认值(T).Equals(值);
}
否则{
返回Object.Equals(null,value);
}
}
私有字符串DefaultStringForType(){
if(类型(T).IsValueType){
返回默认值(T).ToString();
}
否则{
返回“null”;
}
}
我正在使用类似的方法检查泛型类型是否为null:
if (Equals(result, Default(T)))
然后,如果您比较整数,它将打印“null”而不是0。使测试失败难以理解的方法;)这会给我一个编译器警告“不能将运算符==应用于'TExpected'和'TExpected'类型的操作数@Jon这是真的,但这是消除符合参数的警告的唯一方法:p问题不在于如何消除警告。它问我该怎么办:)@Jon-很公平。。。(现在,“优雅地承认”的表情符号在哪里)我已经添加了“//我已经得到斯凯特先生的明确许可,可以忽略这个警告。”似乎是在耍把戏:)@panamack:我可以要求在“斯凯特的”中加一个撇号吗?Ta.当然,“//我得到Skeet先生(此处添加撇号)的明确许可,可以忽略此警告。”值得注意的是,如果有人真的被错误消息困扰,他们总是可以执行
Object.ReferenceEquals(objA,null)
,这实际上只是在.NET源代码中调用objA==objB
。而且,我很确定这将是紧张的或内联的方式。好消息是错误消息消失了,调用仍然有效:)为了完整性,Eric Lippert指出JIT实际上将“val==null”检查替换为“false”当为不可为空的值类型的类型参数编译方法时。但我认为他想与null
@CodeInChaos比较:default
引用类型的null
@Jason,但对于不可为空的值类型,它不是null
。对于没有null
的类型,比较简单地变成常量false
是有意义的。这可能是OPs代码所需要的行为。@CodeInChaos:default(Nullable)
其中T
是不可为空的值类型,是Nullable
的实例,其中Nullable.HasValue
是false
(即null
)@Jason我知道,这与我反对你的密码无关。您的DefaultStringForType
无法正确处理null
的null
。除此之外,OP的代码比你的干净多了。小心<代码>默认值(int)为0,可以是一个有效且显式设置的值。检查default(T)
与检查null有很大的不同。+1到@ANeves,resharper在帮助页面中建议了这一点,对我来说,代码有味道我也讨厌这个例子,因为显然大多数人都希望调用0.ToString()
。。。