2017-04-08 98 views
4

最近我发现,下面的代码在VS2017中编译并按预期工作。但是我找不到任何关于此的主题/文档。所以我很好奇的是它合法使用这个语法:使用带有“null”关键字的“is”关键字c#7.0

class Program 
{ 
    static void Main(string[] args) 
    { 
     var o = new object();    
     Console.WriteLine(o is null); 
     o = null; 
     Console.WriteLine(o is null); 
     Console.ReadLine(); 
    } 
} 

顺便说一句,这是不是在VS2015

+5

https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/第二部分。这与模式匹配有关。 –

回答

13

是的,这是完全有效的工作。这使用C#7的模式匹配功能,该功能可用于is表达式和switch/case语句。 (它需要C#7的事实是,为什么它不是在VS2015为你工作。)例如:

// Type check, with declaration of new variable 
if (o is int i) 
{ 
    Console.WriteLine(i * 10); 
} 
// Simple equality check 
if (o is 5) {} 

平等检查像后者那样 - 尤其是对null - 不太可能成为非常有用的is模式匹配,但对于开关/情况更加有用:

switch (o) 
{ 
    case int i when i > 100000: 
     Console.WriteLine("Large integer"); 
     break; 
    case null: 
     Console.WriteLine("Null value"); 
     break; 
    case string _: 
     Console.WriteLine("It was a string"); 
     break; 
    default: 
     Console.WriteLine("Not really sure"); 
     break; 
} 

对于C#7功能的更多细节,请参见MSDN blog post by Mads Torgersen

+0

哦,我明白了。所以它就像一个类型检查,铸造和比较。 –

+0

@GorRustamyan:模式匹配目前主要是关于类型和相等性检查,其中关于switch/case的guard子句,但它可能会随着时间显着扩展。 –

5

是的,这是有效的写o是空,但这并不等同于Ø== NULL。 代码

static bool TestEquality(object value) => value == null; 

编译成以下IL指令。

IL_0000: ldarg.0 
    IL_0001: ldnull 
    IL_0002: ceq 
    IL_0004: ret 

模式匹配的情况下编译方式如下:

static bool TestPatternMatching(object value) => value is null; 

    IL_0000: ldnull 
    IL_0001: ldarg.0 
    IL_0002: call  bool [System.Runtime]System.Object::Equals(object, object) 
    IL_0007: ret 

所以,模式匹配o是空相当于

Object.Equals(value, null); 

所以,在大多数情况下o为空o == null将表现相同的方式。除平等变体之外有点快。 但是!如果我们用以下类代替对象,情况将会发生巨大变化。

class TestObject 
{ 
    public static bool operator ==(TestObject lhs, TestObject rhs) => false; 
    public static bool operator !=(TestObject lhs, TestObject rhs) => false; 
} 

和方法与

static bool TestEquality(TestObject value) => value == null; 
static bool TestPatternMatching(TestObject value) => value is null; 

模式匹配将保持不变,但平等的变体将使用以下IL

IL_0000: ldarg.0 
    IL_0001: ldnull 
    IL_0002: call  bool PatternMatchingTest.TestObject::op_Equality(class PatternMatchingTest.TestObject, class PatternMatchingTest.TestObject) 
    IL_0007: ret 

在这里我们可以看到,==运营商按预期使用TestObject的过载。但是○为空○== null将给出不同的结果。所以要小心使用模式匹配运算符。