Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “与”的区别是什么;x为空”;及;x==null";?_C#_.net_Null_Pattern Matching_C# 7.0 - Fatal编程技术网

C# “与”的区别是什么;x为空”;及;x==null";?

C# “与”的区别是什么;x为空”;及;x==null";?,c#,.net,null,pattern-matching,c#-7.0,C#,.net,Null,Pattern Matching,C# 7.0,在C#7中,我们可以使用 if (x is null) return; 而不是 if (x == null) return; 使用新方法(前一个例子)比旧方法有什么优势吗 语义有什么不同吗 这只是口味的问题吗?如果没有,我什么时候应该使用其中一个 参考:。更新:已更新Roslyn编译器,以在没有重载相等运算符时使两个运算符的行为相同。请参阅代码中的(M1和M2)显示在没有重载相等比较器时发生的情况。它们现在都有更好的执行=行为。如果存在重载的相等比较器 有关Roslyn编译器的旧版本,请参阅

在C#7中,我们可以使用

if (x is null) return;
而不是

if (x == null) return;
使用新方法(前一个例子)比旧方法有什么优势吗

语义有什么不同吗

这只是口味的问题吗?如果没有,我什么时候应该使用其中一个


参考:。

更新:已更新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");
}
测试产生
a
。如果你把它与你通常会写的东西相比,它确实会有很大的不同<代码>is考虑了比较另一侧的类型。太酷了

我认为,
==null
为null
常量模式只是“偶然”中非常熟悉的一种模式,其中
的语法为
运算符,而equals运算符产生相同的结果


如评论所述

的IL为

用于
==
的IL:

由于我们讨论的是
null
,因此没有什么区别。当您重载相等运算符时,这可能会更改。

重载相等运算符 实际上,当您将
null
与重载了
=
运算符的类型进行比较时,这两个比较在语义上存在差异
foo为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);
    }

    // ...
}
foo的IL代码为空
使用
ceq
指令执行直接参考比较:

IL_0003:  ldloc.0     // foo
IL_0004:  ldnull      
IL_0005:  ceq
foo==null的IL代码使用对重载运算符的调用:

IL_0016:  ldloc.0     // foo
IL_0017:  ldnull      
IL_0018:  call        UserQuery+Foo.op_Equality
因此,不同之处在于,如果使用
==
,则可能会运行用户代码(这可能会有意外的行为或性能问题)

对仿制药的限制 使用
is null
构造将类型限制为引用类型。编译器确保这一点,这意味着您不能对值类型使用
为null
。如果有泛型方法,则除非泛型类型被约束为引用类型,否则将无法使用
is null

bool IsNull<T>(T item) => item is null;                  // Compile error: CS0403
bool IsNull<T>(T item) => item == null;                  // Works
bool IsNull<T>(T item) where T : class => item is null;  // Works
bool为空(T项)=>项为空;//编译错误:CS0403
bool IsNull(T项)=>item==null;//作品
bool为null(T item),其中T:class=>item为null;//作品

感谢您指出这一点。

当您尝试将非空变量与空值进行比较时,也存在差异。当使用
=
时,编译器将发出警告,而当使用
时,编译器将发出错误。很有可能,99%的情况下,您希望编译器因为这样一个基本错误而对您大喊大叫+
的1为空


用NetCore3.1测试了p.S.

这是我刚才看到的链接,但是它没有给你多少信息,这就是为什么我猜OP会问这个问题的原因。页面最重要的部分是这个测试是运算符“是”运算符用于检查对象的运行时类型是否与给定类型兼容。换句话说,我们使用“is”操作符来验证对象的类型是否是我们期望的类型。让我们看看它的语法:@SimonPrice,它是关于当前版本的C#:C#6的。这个问题是关于C#7的,它有。@bigown你在寻找什么样的细节?@PatrickHofman是那种斯维克式的回答,作者example@PatrickHofman但是结果应该是一样的,正如你所说的。始终要注意,
==
是一个可重载的运算符。你可以随心所欲地使用它。例如,这不会告诉你你的实例是否真的为空<另一方面,如果代码中有
ReferenceEquals
,VS 2017灯泡会建议更改为
is null
,而不是
==null
(正确)。@patrickhoffman@svick两个null检查现在编译成相同的东西,因此,
is
在用于检查null时不再具有函数调用的开销。有关证据,请参见@svick在评论中发布的链接。@AndreasBjørnHassingNielsen更新了我的答案。@Patrickhoffman不应该反过来吗?==调用System.Object::Equals(Object,Object)和is null调用ceqIn加法,注意:如果x是泛型类型,则(x为null)需要类约束,而(x==null)和Object.ReferenceEquals(x,null)则不需要。还应注意,null合并运算符(?)和null合并赋值运算符(??=)与“is”类似也忽略重载的等于运算符(=)。
IL_0016:  ldloc.0     // foo
IL_0017:  ldnull      
IL_0018:  call        UserQuery+Foo.op_Equality
bool IsNull<T>(T item) => item is null;                  // Compile error: CS0403
bool IsNull<T>(T item) => item == null;                  // Works
bool IsNull<T>(T item) where T : class => item is null;  // Works