问题描述
在 C# 7 中,我们可以使用
if (x is null) return;
代替
if (x == null) return;
与旧方法相比,使用新方法(以前的示例)有什么优势吗?
语义有什么不同吗?
这只是品味问题吗?如果没有,我什么时候应该使用一个?
参考:C# 7.0 的新增功能.
更新: Roslyn 编译器已更新,使两个运算符的行为在没有重载时相同等式运算符.请参阅代码在当前编译结果(代码中的M1
和M2
)显示了当没有重载的相等比较器时会发生什么.它们现在都具有更好的 ==
行为.如果有过载的相等比较器,代码仍然不同.
有关旧版本的 Roslyn 编译器,请参阅以下分析.
<小时>对于 null
与我们在 C# 6 中习惯的没有区别.但是,当您将 null
更改为另一个常量时,事情变得有趣了.>
以这个为例:
测试(1);公共无效测试(对象 o){if (o is 1) Console.WriteLine("a");否则 Console.WriteLine("b");}
测试产生a
.如果将它与您通常编写的 o == (object)1
进行比较,它确实会产生很大的不同.is
考虑了比较另一端的类型.太酷了!
我认为 == null
与 is null
常量模式只是偶然"非常熟悉的东西,其中 的语法是
运算符和等于运算符产生相同的结果.
正如 svick 评论的那样, <代码> IS NULL 代码>呼叫<代码> System.Object的::等于(对象,对象)代码>其中==
调用 ceq
.
用于is
的IL:
IL_0000: ldarg.1//将参数 1 加载到堆栈中IL_0001: ldnull//在栈上压入一个空引用IL_0002: call bool [mscorlib]System.Object::Equals(object, object)//调用栈上带有参数的方法IL_0007: ret//从方法返回,可能带有一个值
==
的 IL:
IL_0000: ldarg.1//将参数 1 加载到堆栈中IL_0001: ldnull//在栈上压入一个空引用IL_0002: ceq//如果 value1 等于 value2,则压入 1(int32 类型),否则压入 0IL_0004: ret//从方法返回,可能带有一个值
既然我们在谈论 null
,没有区别,因为这个 只对实例产生影响.当您重载相等运算符时,这可能会改变.
In C# 7, we can use
if (x is null) return;
instead of
if (x == null) return;
Are there any advantages to using the new way (former example) over the old way?
Are the semantics any different?
Is it just a matter of taste? If not, when should I use one over the other?
Reference: What’s New in C# 7.0.
Update: The Roslyn compiler has been updated to make the behavior of the two operators the same when there is no overloaded equality operator. Please see the code in the current compiler results (M1
and M2
in the code) that shows what happens when there is no overloaded equality comparer. They both now have the better-performing ==
behavior. If there is an overloaded equality comparer, the code still differs.
See for older versions of the Roslyn compiler the below analysis.
For null
there isn't a difference with what we are used to with C# 6. However, things become interesting when you change null
to another constant.
Take this for example:
Test(1);
public void Test(object o)
{
if (o is 1) Console.WriteLine("a");
else Console.WriteLine("b");
}
The test yields a
. If you compare that to o == (object)1
what you would have written normally, it does make a hell of a difference. is
takes in consideration the type on the other side of the comparison. That is cool!
I think the == null
vs. is null
constant pattern is just something that is very familiar 'by accident', where the syntax of the is
operator and the equals operator yield the same result.
As svick commented, is null
calls System.Object::Equals(object, object)
where ==
calls ceq
.
IL for is
:
IL_0000: ldarg.1 // Load argument 1 onto the stack
IL_0001: ldnull // Push a null reference on the stack
IL_0002: call bool [mscorlib]System.Object::Equals(object, object) // Call method indicated on the stack with arguments
IL_0007: ret // Return from method, possibly with a value
IL for ==
:
IL_0000: ldarg.1 // Load argument 1 onto the stack
IL_0001: ldnull // Push a null reference on the stack
IL_0002: ceq // Push 1 (of type int32) if value1 equals value2, else push 0
IL_0004: ret // Return from method, possibly with a value
Since we are talking about null
, there is no difference since this only makes a difference on instances. This could change when you have overloaded the equality operator.
这篇关于“x 为空"和“x 为空"有什么区别?和“x == null"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!