36

With the release of C# 9.0, the negated null constant pattern was introduced.

The documentation for pattern matching states:

Beginning with C# 9.0, you can use a negated null constant pattern to check for non-null, as the following example shows:

if (e is not null)
{
    // ...
}

Is there any difference between e is not null and e != null, besides the syntax?

surfmuggle
  • 5,527
  • 7
  • 48
  • 77
Pawel
  • 900
  • 2
  • 10
  • 19
  • 13
    [Constant pattern](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#constant-pattern): "The compiler guarantees that no user-overloaded equality operator == is invoked ..." – Damien_The_Unbeliever Sep 21 '21 at 10:18
  • 6
    Its funny, the text you copied for your question, is one line below the answer you were looking for – TheGeneral Sep 21 '21 at 10:21
  • 1
    Ha!! Got the answer then :) Thanks, I didn't spot that. – Pawel Sep 21 '21 at 10:25
  • 3
    Essentially the compiler will convert it to `(object)e!= null` which assures no pesky overloaded equality operators are involved – TheGeneral Sep 21 '21 at 10:26
  • 2
    _"pesky overloaded equality operators"_ That's what we should call them. Always. – Fildor Sep 21 '21 at 10:29

2 Answers2

37

The main difference between e != null and e is not null is the way the the compiler executes the comparison.

Microsoft: "The compiler guarantees that no user-overloaded equality operator == is invoked when expression x is null is evaluated."

Bottom Line: If you are writing code that you don't want to depend on someone's implementation of the != and == operators, use is null and is not null because it is safer.

See the following example:

public class TestObject
{
  public string Test { get; set; }

  // attempt to allow TestObject to be testable against a string
  public static bool operator ==(TestObject a, object b)
  {
    if(b == null)
      return false;
    
    if(b is string)
      return a.Test == (string)b;

    if(b is TestObject)
      return a.Test == ((TestObject)b).Test;

    return false;
  }

  public static bool operator !=(TestObject a, object b)
  {
    if(b == null)
      return false;
    
    if(b is string)
      return a.Test != (string)b;

    if(b is TestObject)
      return a.Test != ((TestObject)b).Test;

    return false;
  }
}

If you have code that needs to ensure that an object isn't null, using is not null will give you better results with TestObject than using != null because the overload of the ==/!= operators is a little odd.

Console example 1:

TestObject e = null;

if(e == null)
  Console.WriteLine("e == null");

if(e is null)
  Console.WriteLine("e is null");

Output: e is null

Console example 2:

TestObject e = new TestObject();

if(e != null)
  Console.WriteLine("e != null");

if(e is not null)
  Console.WriteLine("e is not null");

Output: e is not null

Neither overloaded operator is implemented "correctly" so the Console never outputs e == null or e != null.

Kyle B
  • 2,328
  • 1
  • 23
  • 39
14

The only difference (besides the syntax) is, that the compiler guarantees that no user-overloaded operator is called when using is not null instead of != null (or is null instead of == null).

From operator overloading:

A user-defined type can overload a predefined C# operator. That is, a type can provide the custom implementation of an operation in case one or both of the operands are of that type. The Overloadable operators section shows which C# operators can be overloaded.

mamen
  • 1,202
  • 6
  • 26
  • 1
    Can you please expand on what you mean by "user-overloaded operator"? – Lukas Nov 02 '22 at 14:19
  • 2
    In C# you can overload operators to alter the default handling of them. For more information, see [the official documentation for operator overloading](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading) – mamen Nov 02 '22 at 15:40
  • 2
    This isn't the **only** difference - the compiler will not let you use `x is null` or `x is not null` when dealing with structs - it will issue an error: *CS0037: Cannot convert null to '' because it is a non-nullable value type*, but it will let you use `x == null` or `x != null` (with a warning - *CS0472: The result of the expression is always 'false' since a value of type '' is never equal to 'null'*). – Zohar Peled May 30 '23 at 09:02
  • It seems like `structs` are a special case then for which the `is null` and `is not null` patterns cannot be used. But this was not the question. If OP got an error for `is not null`, the question would have been another. You can however edit my answer if you want and add this special case as an info. – mamen May 30 '23 at 12:46