Recently i find out, that the following code compiles and works as expected in VS2017. But i can't find any topic/documentation on this. So i'm curious is it legit to use this syntax:
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 this is not working in VS2015
Yes, it's entirely valid. This uses the pattern matching feature of C# 7, which is available with is
expressions and switch/case
statements. (The fact that it requires C# 7 is why it isn't working for you in VS2015.) For example:
// Type check, with declaration of new variable
if (o is int i)
{
Console.WriteLine(i * 10);
}
// Simple equality check
if (o is 5) {}
Equality checks like the latter - particularly for null
- aren't likely to be very useful for is
pattern matching, but are more useful for 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;
}
For more details of C# 7 features, see the MSDN blog post by Mads Torgersen.
Yes, it is valid to write o is null, but this is not equivalent to o == null.
The code
static bool TestEquality(object value) => value == null;
compiles into following IL instructions.
IL_0000: ldarg.0
IL_0001: ldnull
IL_0002: ceq
IL_0004: ret
The pattern matching case compiled in following manner:
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
So, pattern matching o is null is equivalent to
Object.Equals(value, null);
So, in most cases o is null and o == null will behave in same way. Except equality variant is a bit faster. BUT! Things will change dramatically, if we replace object with following class.
class TestObject
{
public static bool operator ==(TestObject lhs, TestObject rhs) => false;
public static bool operator !=(TestObject lhs, TestObject rhs) => false;
}
and methods with
static bool TestEquality(TestObject value) => value == null;
static bool TestPatternMatching(TestObject value) => value is null;
The pattern matching will stay same, but the equality variant will use following 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
Here we can see, that == operator is using TestObject's overload as expected. But o is null and o==null will give different results. So be careful using pattern matching is operator.