2017-04-08 69 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將給出不同的結果。所以要小心使用模式匹配運算符。