模式匹配 equal null vs is null

Pattern matching equal null vs is null

来自 Microsoft new-features-in-c-7-0:

public void PrintStars(object o)
{
    if (o is null) return;     // constant pattern "null"
    if (!(o is int i)) return; // type pattern "int i"
    WriteLine(new string('*', i));
}

o == nullo is null有什么区别?

o is null翻译成object.Equals(null, o)(大家可以看看here)。

object.Equals代码is written as:

public static bool Equals(Object objA, Object objB)
{
    if (objA == objB)
    {
        return true;
    }
    if (objA == null || objB == null)
    {
        return false;
    }
    return objA.Equals(objB);
}

所以最后会有一个o == null(第一个if)。请注意,System.Object 没有定义 operator==,因此使用的是引用类型,即引用相等性。

理论上,通过观察被调用的代码,可以认为 o == nulloSystem.Object)应该比 o is null(更少的操作)更快。 .. 但是谁知道呢? :-)

最终的结果是,通过两条不同的路线,o is nullo == null(with o a System.Object)return结果相同。

通过查看我们甚至可以看到 o == nullobject.ReferenceEquals(o, null) 相同(oSystem.Object):-)。

有趣的问题应该是,为什么 C# 编译器不将 x is null 翻译成 object.ReferenceEquals(x, null)。请注意,由于如何完成可空类型的装箱,它甚至可以用于:

int? a = null;
if (a is null) { /* */ }

对编译器的更改使此响应无效...如果您单击 "here" link 您可以看到它

"is" 和 == 之间的区别是 "is" 特别之处在于,如果您与值进行比较,它充当 ==,而当您将对象的类型与类型进行比较时,它充当 typeof(type)。

由于@xanatos的答案已经过时了(但只在最后提到)我正在写一个新的,因为我也想知道这个并研究它。

简而言之:如果不重载==运算符,那么o == nullo is null是一样的。
如果你确实重载了 == 运算符,那么 o == null 会调用它,但是 o is null 不会 .

o is null 总是与 ReferenceEquals(o, null) 做同样的事情,即它 检查值是否为 null,它不调用任何运算符或 Equals 方法。

更长的答案: here is a SharpLab sample 展示了检查 null 的各种方法。

如果您以 IL 形式查看结果,您会看到:

  • is nullReferenceEquals 产生相同的代码
  • o == null 将调用重载的 operator==
  • object.Eqauls(o, null) 调用该方法
  • 如果您在 class C 中注释 operator==,您将看到 o == null 现在生成与 o is null
  • 相同的代码