应该在左侧还是右侧检查 null?

7

在审查一些代码时,我看到了以下内容:

if (null == condition) { ... }

我也注意到了:

if (condition == null) { ... }

我记得将null放在左边有优势,但我忘了具体是什么了。我想这可能是.NET运行时的一个旧特性,在较新的.NET运行时中已经被优化掉了。我倾向于使用后一种空值检查方法,所以前一种方法会引起我的注意。

那么这是一个风格问题,还是将null放在左边或右边有优势呢?


3
在编译器开始生成关于此问题警告之前,早期版本的C语言中存在一种黑客技巧。在C#中不是问题,因为它有一个bool类型,不像C语言那样,所以当你写if (obj = null) {}时,它会发出警告。 - Hans Passant
3个回答

9

在C语言风格中,常见的原因是为了防止将等号==误写成赋值符号=。你不能将常量赋值 - 也就是说以下操作是非法的,编译器会捕获这个错误:

if (false = condition) { ... }

与此相反,这是完全合法的(但可能不是作者想要的):

if (condition = false) { ... }

注意:与普通的C语言相比,这个问题在C#中有限制,因为如下评论所述,if语句需要一个bool值。所以只有当你的类型是bool时,才会出现问题。


请注意,在 C# 中,这通常不是问题,除非涉及布尔变量 - 无论如何都不能将其与 null 进行比较(而 bool? 不是 if 语句中的有效类型)。 - Rob
1
这在 C# 中是不合法的,因为“if”需要一个“bool”,而“null”不能分配给“bool”。 - juharr
1
@juharr 这是合法的 C# 代码,因为我们不知道 condition 的类型,所以它可能是一个重载了 truefalse 运算符的类型。 - Jon Hanna
@JonHanna 我的评论是关于这个答案有 if(condition = null) 的时候。现在如果 condition 是一个 bool,那么 if(condition = false) 是完全合法的,但是如果像你所说的它是一个从 bool 隐式转换而来的类型,那么除非它也有一个隐式转换到 bool,否则它将不合法。 - juharr
@juharr 我的回复也是在回答中有 if (condition = null) 的情况下(尽管有一个横幅表示答案已被编辑)。我忘记了隐式转换,但在没有任何关于不存在这种转换的信息的情况下,它也是有效的。我想到了 true 运算符,这也使它有可能有效。两者都足以让给定的代码有效,因为作为给定信息的代码没有关于类型的信息,这可能会使其无效。 - Jon Hanna
谢谢您的回答。+1 - David Hoerster

7

在三种情况下,它可以产生影响。

第一种情况是在if语句中,condition = null的拼写错误是有效的。这在C类语言中更为常见,它们允许nullif中(被视为false),这是它们的大多数情况,但不包括C#。

在C#中,有可能创建具有此效果的类型:

public class Test
{
  public static bool operator true(Test x)
  {
    return true;
  }
  public static bool operator false(Test x)
  {
    return false;
  }
}
void Main()
{
  Test test = new test();
  if (test = null)
  {
    Console.WriteLine("!");
  }
}

这些运算符重载的使用场景并不多,特别是自从.Net 2.0引入泛型后(对于像SqlBoolean这样的类型仍具有更高的价值,它使得一个值可以表示truefalsenull,我们现在会使用bool?)。因此,在C#中,这种情况相当边缘化。
另一种情况类似,如果存在到bool或实现truefalse运算符的类型的隐式转换:
void Main()
{
  Test test = new Test();
  if (test = null)
  {
    Console.WriteLine("!");
  }
}
public class Test
{
  public static implicit operator bool(Test x)
  {
    return true;
  }
}

避免使用隐式类型转换操作符的原因有几个,但是相较于第一个例子,这种情况略微更有可能发生,但仍然不常见。

另一个情况是如果==被非对称地重载了:

public class Test
{
  public static bool operator == (Test x, Test y)
  {
    return ReferenceEquals(x, null);
  }
  public static bool operator !=(Test x, Test y)
  {
    return !(x == y);
  }
}
void Main()
{
  Test test = new Test();
  if (test == null)
  {
    Console.WriteLine("This won't print.");
  }
  if (null == test)
  {
    Console.WriteLine("This will print.");
  }
}

但是,由于非对称的==总是一个错误,因此这取决于操作符存在错误才会产生任何影响。这种情况可能比第一种情况更常见,但当它发生时应该进行修复,因此它的实际影响更小。

因此,在C#中它可以产生影响,但这种情况很少出现,大多数情况都是基于其他人做了不应该做的事情。

因此,这主要是一种风格问题。将null放在前面的人往往是从使得顺序更重要的语言中学来的。


感谢您提供详细的答案。+1 - David Hoerster

3

无论 (null == condition) 如何编译,使用 典型的 值,如 null 作为第一个(左)操作数是不直观的。相反,第一个操作数应提示您打算评估什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接