使用 "is" 关键字和 "null" 关键字 c# 7.0
Using "is" keyword with "null" keyword c# 7.0
最近我发现,以下代码在 VS2017 中按预期编译和工作。但我找不到任何关于此的 topic/documentation。所以我很好奇使用这种语法是否合法:
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 的 模式匹配 功能,该功能可用于 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/case:[=17 更有用=]
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。
是的,写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 为 null 并且 o == null 将以相同的方式运行。除了平等变体有点快。 但是! 如果我们将 object 替换为以下 class,事情将会发生巨大的变化。
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 为 null 并且 o==null 将给出不同的结果。所以要小心使用模式匹配 is 运算符。
最近我发现,以下代码在 VS2017 中按预期编译和工作。但我找不到任何关于此的 topic/documentation。所以我很好奇使用这种语法是否合法:
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 的 模式匹配 功能,该功能可用于 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/case:[=17 更有用=]
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。
是的,写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 为 null 并且 o == null 将以相同的方式运行。除了平等变体有点快。 但是! 如果我们将 object 替换为以下 class,事情将会发生巨大的变化。
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 为 null 并且 o==null 将给出不同的结果。所以要小心使用模式匹配 is 运算符。