作者:摩羯水瓶的微博w | 来源:互联网 | 2023-02-07 11:00
最近我发现,以下代码在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中无效
1> Jon Skeet..:
是的,它完全有效.这使用了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更有用:
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功能的更多详细信息,请参阅Mads Torgersen撰写的MSDN博客文章.
2> Gor Rustamya..:
是的,写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将以相同的方式运行.除了等式变体有点快.但!如果我们用下面的类替换对象,事情会发生巨大变化.
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将给出不同的结果.所以要小心使用模式匹配是运算符.