空引用检查的好习惯是什么?

时间:2011-01-31 10:56:13

标签: c# performance

检查对象上的空引用的最有效方法是什么?我见过各种代码示例,它们有不同的方法来检查以下哪种方法最有效,或者被认为是最佳使用的方法?

Object.ReferenceEquals(item, null)

item == null

item != null

Object.Equals(item, null)

感谢

7 个答案:

答案 0 :(得分:8)

  1. Object.ReferenceEquals(item, null)将引用和等于item == null
  2. 进行比较
  3. Object.Equals(item, null)比较引用类型的引用和值类型的按位,但在反射器中它等于(item == null) || ((item != null && null != null) && item.Equals(null))
  4. item != null代码并不总是等于!(item == null),但结果当然应该相等。
  5. item == null代码不等于null == item,类似于typeof(item).Equals(object)object.Equals(typeof(item))方法调用。
  6. 它有所不同,因为您可以覆盖!===Equals。 使用已知实现的方法,null == item更适合编码,但更难阅读。 Object.ReferenceEquals(null, item)可能更快或更快。

    P.S。也使用string.IsNullOrEmpty(item)

答案 1 :(得分:5)

为了与null进行比较,我始终使用==!=,因为对于null,它应始终提供与ReferenceEquals相同的结果,无论如何Equals(所以不需要额外的代码)。

修改==确实可以覆盖null以便为true(即==)提供错误的结果,但这意味着覆盖错误。为了使代码可读,我会坚持使用!=和{{1}}。

答案 2 :(得分:3)

ReferenceEquals相当于(object)o1==(object)o2。如果等于运算符过载,它可能比o1==o2更快。 Object.Equals可能有点慢。

==!=之间的差异不是表现,而是程序的外观。如果==!=运算符过载,它们可能会慢一些。

但我认为它们之间的性能差异根本不重要。我会选择最容易阅读的那个。这通常是==!=

如果我抛出异常,我通常会使用==,如下所示:

if(o == null)
  throw new ...;

如果null导致无操作,则通常!=是合适的

if(x != null)
{
   ...
}

答案 3 :(得分:3)

作为额外的,不要忘记.NET 4.0中的代码合约!

System.Diagnostics.Contracts.Contract.Requires(item != null);

这不仅好看而且清晰,但允许编译时间检查。请参阅msdn。中的Code Contracts

答案 4 :(得分:3)

更新回答

从C#7.0起,您可以使用:

item is null

应该是最简单,最简单的方式。它与ReferenceEquals检查相同。


旧答案:

<强> 1)

Object.ReferenceEquals(item, null)

这是一个好方法。不像我喜欢的那样简洁,但仍然很好并且完全告诉你意图。

<强> 2)

item == null

item != null

如果您确定==并且随后!=正确重载,则此处(最优雅)没有任何问题。它易于编写(重载)坏的等式运算符(并且经常完成)。但真正的麻烦在于你试图在类中重载==运算符(比如说值语义)。 您无法在==重载类since that will cause an infinite recursion 的函数内使用==进行空值检查。为了拥有一致的风格,我依靠别的东西。

第3)

Object.Equals(item, null)

同样它在内部做了一个ReferenceEquals所以没有多大意义,但如果它在语义上对你更有意义,那就去吧。

<强> 4)

我的方法是做

(object)item == null

我依赖于object自己的等式运算符,它不会出错。不太可读,所以我只是包装自定义扩展方法和重载:

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null;
}

public static bool IsNull<T>(this T? obj) where T : struct
{
    return !obj.HasValue;
}

这更有意义,因为我需要经常检查DBNull。所以现在我有一个一贯的风格!

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null || obj == DBNull.Value;
}

(不要取消(object)投射,因为如前所述,当重载==时会阻止无限递归

此外,约束会阻止IsNull值类型。现在它像打电话一样甜蜜

object obj = new object();
Guid? guid = null; 
bool b = obj.IsNull(); // false
b = guid.IsNull(); // true
2.IsNull(); // error

我也发现(object)item == null very very very slightly faster than Object.ReferenceEquals(item, null)object.Equals(,)就此问题,但只有在重要的时候(我正在研究我要微观优化一切的事情) !)。

要查看有关实施平等检查的完整指南,请参阅What is "Best Practice" For Comparing Two Instances of a Reference Type?

答案 5 :(得分:2)

我总是使用

item != null

但这比

更难阅读
item == null

Object.ReferenceEquals用于检查两个对象是否是同一个实例。

答案 6 :(得分:-1)

前2个是有效的。

但是最后一个不仅进行了引用检查,而且不应该用于空检查。