“is not null”和“!= null”有什么区别?

48

随着C# 9.0的发布,引入了否定的空值常量模式。

模式匹配的文档说明如下:

从C# 9.0开始,您可以使用否定的空值常量模式来检查非空值,如以下示例所示:

if (e is not null)
{
    // ...
}
除了语法之外,“e is not null”和“e != null”之间是否有任何区别?


15
“常量模式”:编译器保证不会调用任何用户重载的相等运算符 == … - Damien_The_Unbeliever
6
有趣的是,你复制到问题中的文本,就在你要寻找答案的那一行下面。 - TheGeneral
1
哈哈!找到答案了 :) 谢谢,我没注意到。 - Pawel
4
基本上,编译器会将其转换为(object)e!= null,以确保不涉及任何烦人的重载相等运算符。 - TheGeneral
3
“讨厌的重载等号运算符” 这就是我们应该称呼它们的。总是这样。 - Fildor
离题:为什么人们讨厌问题,但喜欢答案? - Pawel
2个回答

48
e != nulle is not null之间的主要区别在于编译器执行比较的方式。

Microsoft: "当评估表达式x是否为null时,编译器保证不会调用任何用户重载的等号运算符==。"

底线:如果您正在编写不希望依赖于某人的!===运算符实现的代码,请使用is nullis not null,因为它更安全。

请参见以下示例:

public class TestObject
{
  public string Test { get; set; }

  // attempt to allow TestObject to be testable against a string
  public static bool operator ==(TestObject a, object b)
  {
    if(b == null)
      return false;
    
    if(b is string)
      return a.Test == (string)b;

    if(b is TestObject)
      return a.Test == ((TestObject)b).Test;

    return false;
  }

  public static bool operator !=(TestObject a, object b)
  {
    if(b == null)
      return false;
    
    if(b is string)
      return a.Test != (string)b;

    if(b is TestObject)
      return a.Test != ((TestObject)b).Test;

    return false;
  }
}

如果您有需要确保对象不为空的代码,使用 is not nullTestObject 搭配会比使用 != null 更好,因为==/!= 运算符的重载有点奇怪。

控制台示例1:

TestObject e = null;

if(e == null)
  Console.WriteLine("e == null");

if(e is null)
  Console.WriteLine("e is null");

输出:e 为空

控制台示例2:

TestObject e = new TestObject();

if(e != null)
  Console.WriteLine("e != null");

if(e is not null)
  Console.WriteLine("e is not null");

输出:e 不为 null

由于没有正确实现任何重载运算符,因此控制台从不输出 e == nulle != null


17

除了语法之外,唯一的区别是编译器保证在使用is not null代替!= null(或is null代替== null)时不会调用用户重载的运算符。

来自运算符重载

用户定义的类型可以重载预定义的 C# 运算符。也就是说,如果一个或两个操作数是该类型,则该类型可以提供操作的自定义实现。可重载运算符部分显示了哪些 C# 运算符可以被重载。


1
请问您能否详细解释一下“用户重载运算符”是什么意思? - Lukas
2
在C#中,您可以重载运算符以更改它们的默认处理方式。有关更多信息,请参阅运算符重载的官方文档 - mamen
3
这不是唯一的区别——编译器不允许在处理结构时使用x is nullx is not null,它会发出错误:CS0037: Cannot convert null to '<your type>' because it is a non-nullable value type,但它会让你使用x == nullx != null(带有警告-* CS0472: The result of the expression is always 'false' since a value of type '<your type>' is never equal to 'null'*)。 - Zohar Peled
似乎 structs 是一个特殊情况,无法使用 is nullis not null 模式。但这不是问题所在。如果 OP 因 is not null 而出现错误,则问题将会是另外一个。然而,如果您希望的话,您可以编辑我的答案并添加此特殊情况作为信息。 - mamen
@Vqf5mG96cSTT 你错了。 - undefined

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