if (x is null) return;
if (x == null) return;
使用新方法(以前的示例)比旧方法有什么优势吗?语义有什么不同吗?
只是口味问题吗?如果没有,我什么时候应该在另一个上使用?
参考:C#7.0的新增功能。
#1 楼
更新:Roslyn编译器已更新,以在没有重载相等运算符时使两个运算符的行为相同。请查看当前编译器结果中的代码(代码中的M1
和M2
),其中显示了没有重载的相等比较器时会发生的情况。它们现在都具有性能更好的==
行为。如果有一个重载的相等比较器,则代码仍然会有所不同。与使用C#6的习惯有所不同。但是,将null
更改为另一个常量时,事情变得很有趣。例如,/>
测试得出
null
。如果将其与通常编写的内容相比较,那确实会有所不同。 a
考虑了比较另一侧的类型。 我认为
o == (object)1
与is
常数模式只是“偶然”而已,在这种情况下,== null
运算符和equals运算符的语法会产生相同的结果。 br /> svick评论,
is null
调用is
,is null
调用System.Object::Equals(object, object)
。 ==
的IL:Test(1);
public void Test(object o)
{
if (o is 1) Console.WriteLine("a");
else Console.WriteLine("b");
}
由于我们正在讨论
ceq
,因此没有区别,因为这仅对实例有所不同。当重载等于运算符时,这可能会改变。评论
@PatrickHofman看起来像是调用object.Equals(x,null),而==编译为ceq。但是结果应该和您说的一样。
– svick
16年11月18日在16:04
始终谨记==是可重载的运算符。您可以使用它进行任何操作。例如这个怪异的实现==不会告诉您您的实例是否真正为空。另一方面,如果为null,则始终为true的null引用返回true :)此外,如果代码中包含ReferenceEquals,则VS 2017灯泡将建议更改为null,而不是== null(正确)。
– nawfal
18年4月19日在13:21
@PatrickHofman @svick现在可以将两个空检查编译为同一件事,因此在用于检查空值时不再具有函数调用的开销。为了证明,请参阅@svick在评论中发布的链接。
– AndreasHassing
18年6月11日在12:48
@AndreasBjørnHassingNielsen更新了我的答案。
–帕特里克·霍夫曼(Patrick Hofman)
18年6月12日在7:46
@PatrickHofman应该不是IL吗? ==调用System.Object :: Equals(object,object)并且为null调用ceq
– ZbigniewLedwoń
19-4-23在6:36
#2 楼
重载的equals运算符在将
null
与已重载==
运算符的类型进行比较时,两个比较之间实际上在语义上存在差异。 foo is null
将使用直接引用比较来确定结果,而foo == null
当然将运行重载的==
运算符(如果存在)。如果第二个参数是==
,则它总是会引发异常:void Main()
{
Foo foo = null;
if (foo is null) Console.WriteLine("foo is null"); // This condition is met
if (foo == null) Console.WriteLine("foo == null"); // This will throw an exception
}
public class Foo
{
public static bool operator ==(Foo foo1, Foo foo2)
{
if (object.Equals(foo2, null)) throw new Exception("oops");
return object.Equals(foo1, foo2);
}
// ...
}
null
的IL代码使用foo is null
指令执行直接引用比较: IL_0003: ldloc.0 // foo
IL_0004: ldnull
IL_0005: ceq
ceq
的IL代码使用对重载运算符的调用:IL_0016: ldloc.0 // foo
IL_0017: ldnull
IL_0018: call UserQuery+Foo.op_Equality
所以区别在于,如果您使用
foo == null
可能会冒着运行用户代码的风险(这可能会导致意外的行为或性能问题)。 。编译器会确保这一点,这意味着您不能在值类型上使用==
。如果您有通用方法,除非将通用类型限制为引用类型,否则将无法使用is null
。感谢David Augusto Villa提供的指出这一点。评论
另外,如果x是泛型类型,则注释(x为null)需要类约束,而(x == null)和object.ReferenceEquals(x,null)则不需要类约束。
–大卫·奥古斯托·维拉
19年11月5日在23:58
#3 楼
当您尝试将非null变量与null值进行比较时,也存在差异。使用==
时,编译器将发出警告,而使用is
时,编译器将发出错误。最有可能在99%的时间里,您希望编译器对这种基本错误大喊大叫。为is null
+1。已通过NetCore3.1在https://dotnetfiddle.net/上进行了测试
评论
那就是我刚才正在查看的链接,但是它没有给您太多信息,这就是为什么我猜OP在问这个问题。页面上最重要的部分是此测试是否为Operator(运算符)“ is”运算符用于检查对象的运行时类型是否与给定类型兼容。换句话说,我们使用“ is”运算符来验证对象的类型是否符合我们的预期。让我们看一下它的语法:@SimonPrice这与C#的当前版本有关:C#6。此问题与C#7有关,它具有模式匹配。
@bigown您要寻找什么样的细节?
@PatrickHofman以示例的方式回答了