来自 c-7-0 中的Microsoft新功能:
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 == null
和o is null
的区别是什么?
由于@xanatos的答案已经过时(但仅在最后提到),我正在写一个新的,因为我也想知道这一点并研究了它。
简而言之:如果您不重载==
运算符,则o == null
和o is null
是相同的.
如果您确实重载了==
运算符,那么o == null
会调用它,但o is null
不会。
o is null
总是做与ReferenceEquals(o, null)
相同的操作,即它只检查值是否为空,它不调用任何运算符或Equals
方法。
更长的答案:这是一个 SharpLab 示例,展示了检查 null 的各种方法。
如果以 IL 形式查看结果,则会看到:
is null
和ReferenceEquals
产生相同的代码o == null
将调用重载operator==
object.Equals(o, null)
调用该方法- 如果您在类
C
中注释operator==
,您将看到o == null
现在生成的代码与o is null
o is null
被翻译成object.Equals(null, o)
(你可以在这里看到它)。
object.Equals
代码编写为:
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 == null
(o
System.Object
)应该比o is null
(更少的操作)更快......但谁知道呢?:-)
最终结果是,通过两条不同的路由,o is null
和o == null
(o
System.Object
)返回相同的结果。
通过查看,我们甚至可以看到o == null
与object.ReferenceEquals(o, null)
相同(o
System.Object
):-)。
有趣的问题应该是,为什么 C# 编译器不将x is null
转换为object.ReferenceEquals(x, null)
?请注意,由于可空类型的装箱方式,它甚至可以用于:
int? a = null;
if (a is null) { /* */ }
对编译器的更改使此响应无效...如果您单击"此处"链接,您可以看到它
"is"和==之间的区别是"is"的特殊之处在于,如果您与值进行比较,它充当==,当您将对象的类型与类型进行比较时,它充当typeof(type)。