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

时间:2017-04-08 14:14:31

标签: c# null keyword 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();
    }
}

BTW这在VS2015中不起作用

2 个答案:

答案 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

答案 1 :(得分:12)

是的,写 o is null 是有效的,但这不等于 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 的重载。但 o为空 o == null 会产生不同的结果。所以要小心使用模式匹配运算符。

相关问题