使用“is”关键字和“null”关键字c#7.0

最近我发现,以下代码在VS2017中编译并按预期工作。 但我找不到任何关于此的主题/文档。 所以我很好奇使用这种语法是否合法:

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中无效

是的,它完全有效。 这使用了C#7的模式匹配function,该function可用于表达式和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 – 对于模式匹配不太可能非常有用,但对于switch / case更有用:

 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#7function的更多详细信息,请参阅Mads Torgersen撰写的MSDN博客文章 。

是的,写o是有效的,但这不等于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为null相当于

 Object.Equals(value, null); 

因此,在大多数情况下, o为nullo == 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的重载。 但是o为nullo == null将给出不同的结果。 所以要小心使用模式匹配运算符。