模式匹配等于null vs为null

时间:2017-03-15 15:34:10

标签: c# c#-7.0

来自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的差异是什么?

3 个答案:

答案 0 :(得分:10)

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 == nullo一个System.Object)应该比o is null更快(操作更少)......但谁知道呢? : - )

最终结果是,通过两条不同的路线o is nullo == nullo一个System.Object)会返回相同的结果。

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

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

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

对编译器的更改使此响应无效...如果您点击“此处”链接即可看到

答案 1 :(得分:1)

由于@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)调用该方法
  • 如果您在类operator==中对C进行注释,您将看到o == null现在产生与o is null相同的代码

答案 2 :(得分:-2)

"之间的差异是"和==是"是"特殊的是,当你比较对象的类型和类型时,如果你比较它并作为typeof(类型),它就作为==。