Man*_*ero 219 .net c# null pattern-matching c#-7.0
在C#7中我们可以使用
if (x is null) return;
Run Code Online (Sandbox Code Playgroud)
代替
if (x == null) return;
Run Code Online (Sandbox Code Playgroud)
使用新方法(前一个例子)比旧语法有什么好处吗?
语义学有什么不同?
只是品味问题?如果没有,何时使用一个或另一个.
参考.
Pat*_*man 190
更新: Roslyn编译器已更新,以便在没有重载的相等运算符时使两个运算符的行为相同.请查看当前编译器结果(M1以及M2代码中)中的代码,该代码显示没有重载的相等比较器时会发生什么.他们现在都有更好的表现==行为.如果存在重载的相等比较器,则代码仍然不同.
请参阅以下分析的旧版Roslyn编译器.
因为null与C#6的习惯没有区别.但是,当你改变null为另一个常量时,事情会变得很有趣.
以此为例:
Test(1);
public void Test(object o)
{
if (o is 1) Console.WriteLine("a");
else Console.WriteLine("b");
}
Run Code Online (Sandbox Code Playgroud)
测试结果a.如果将它与o == (object)1正常情况下的情况进行比较,那确实会产生一些差异.is考虑到比较的另一个站点上的类型.太棒了!
我认为== nullvs. is null常量模式只是"偶然"非常熟悉的东西,其中is运算符和equals运算符的语法产生相同的结果.
正如svick评论的那样,is null调用System.Object::Equals(object, object)哪里==调用ceq.
IL代表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
Run Code Online (Sandbox Code Playgroud)
IL代表==:
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
Run Code Online (Sandbox Code Playgroud)
由于我们正在谈论null,没有区别,因为这只会对实例产生影响.当你重载了相等运算符时,这可能会改变.
Tho*_*sen 54
事实上,两种比较之间在语义上存在差异.当您null与==运算符重载的类型进行比较时,边缘情况会出现.
foo is null将使用直接引用比较来确定结果,而foo == null当然会运行重载==运算符(如果存在).
在这个例子中,我在重载的==运算符中引入了一个"bug",如果第二个参数是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);
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
IL代码foo is null使用该ceq指令执行直接引用比较:
IL_0003: ldloc.0 // foo
IL_0004: ldnull
IL_0005: ceq
Run Code Online (Sandbox Code Playgroud)
IL代码foo == null使用对重载运算符的调用:
IL_0016: ldloc.0 // foo
IL_0017: ldnull
IL_0018: call UserQuery+Foo.op_Equality
Run Code Online (Sandbox Code Playgroud)
所以区别在于,如果您使用==冒险运行用户代码(可能会出现意外行为或性能问题).
Fre*_*ric 12
当您尝试将非空变量与空值进行比较时,也存在差异。使用时==,编译器会发出警告,而使用时is,编译器会发出错误。很可能,在 99% 的情况下,您希望编译器因为这样一个基本错误而对您大喊大叫。+1 为is null。
PS 在https://dotnetfiddle.net/ 上使用 NetCore3.1 进行测试