Roslyn: Consider 'value is null' instead of 'value == null' for the "Add null check" codefix

Created on 15 Jan 2018  路  6Comments  路  Source: dotnet/roslyn

It's possible that there could be a custom operator defined for ==, which could be slower than a simple pointer comparison. is null reads better and is guaranteed to be just a pointer comparison.

This may warrant looking into the user's code style to see if they already have a lot of == nulls or is nulls, to see which codefix should be offered to maintain consistency.

Area-IDE Developer Community Resolution-Fixed

Most helpful comment

We should change the language to permit value is null for an unconstrained generic.

All 6 comments

This is minor (and more of a detail that needs to be considered once this gets implemented), but is null isn't a 1:1 replacement for == null. This code

    public static void M<T>(T value)
    {
        if (value is null) { } //error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type.
    }

does not compile, while value == null would. See also #23581.

We should change the language to permit value is null for an unconstrained generic.

For the sake of completeness, there are some more inconsistencies here (but some might be unresolvable):

```C#
public class C {
//unconstraint
public void UnconstraintIs(T v) {
var b = v is null; //error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
}
public void UnconstraintNull(T v) {
var b = v == null; // Fine
}

//class
public void RefconstraintIs<T>(T v) where T:class {
    var b = v is null; //Fine
}
public void RefconstraintNull<T>(T v)  where T:class {
    var b = v == null; //Fine
}

//struct
public void ValueconstraintIs<T>(T v) where T:struct {
    var b = v is null; //error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
}
public void ValueconstraintNull<T>(T v)  where T:struct {
    var b = v == null; //error CS0019: Operator '==' cannot be applied to operands of type 'T' and '<null>'
}
public void ValueconstraintRefEquals<T>(T v)  where T:struct {
    var b = ReferenceEquals(v, null); // Fine
}

}

[sharplab.io](https://sharplab.io/#v2:C4LglgNgNAJiDUAfAAgZgATIEzoMLoG8BYAKHXPQHpKBnYAJwFcBjYdRgO2YHsO76AhmA7BSFTBmQAWdAFUuvfkJEBJGgB4AKgD4AFJvQA3AJSEx4ioYH10AI3QBeI+jA10HRhAgBuKpQCm9PTcNrgAygAMUhGoIHgCHBzcbDwchoFsHl7owNw5AJ4ADv7ohdYCALb+wIHoAOSadXb+zAKMNCVgKdyeMM3oAu68ALRZEAK2ECVWEIwlwEX+AHR4imAwtcgR9RsAZm0QwPrGTcJ0/gIwS+bkAL43Epgy8qlKwsAAcp4QWnoGJmYyBZyFYbPYnIZHE4xr5qOgAGLCfwPe4kB7UbAPNBPdAAJX8u1eDGUwDUv30RlMAHcABaBEqaEDYQHAkHWOyOZyudzfWGUREcZFAu5YyQyfGExTE95fLzk/6mdC0+noRnM4jCiygjkQqE8rx8gVC8SogCQ6NoDBYok12Ok6AAagJZi0pYJ3mSdBSAcr6AyQPxrSzWdrwVy3DC/IFgqFItFYvFEsl0Kl0vRMt8cnkFsVSuUqjUbA0mrYWm0Oi5ur1+oMkhxRt8JlMjM65gViitcGsNjYtjsCQcjpoTi4+DVLtdNajxHaZE6XUT3SJZT8vQryL7/YHWMHgaHOZCHNDeVGgiE8JEIgBGACccQA8sVBLki0emq0k2xSwNCoUIGB/D6XJ0G4J8EhgNxuF2dsSmLAYOD6Op1DGbQ6hRUUcXnOZFxJCUAFEAEdGGdDQ10pDc6T9VUAytHcNVZFswU5CV6S4fxCOIiAaF0QwoH1CBjD5BEkXQkhbiAA=)

```VB
Public Class C
    Public Sub UnconstraintIs(Of T)(v As T)
        Dim flag As Boolean = v Is Nothing
    End Sub

    Public Sub RefconstraintIs(Of T As Class)(v As T)
        Dim flag As Boolean = v Is Nothing
    End Sub

    Public Sub ValueconstraintIs(Of T As Structure)(v As T)
        Dim flag As Boolean = v Is Nothing ' error BC30020: 'Is' operator does not accept operands of type 'T'. Operands must be reference or nullable types.
    End Sub

    Public Sub ValueconstraintReferenceEquals(Of T As Structure)(v As T)
        Dim flag As Boolean = ReferenceEquals(v, Nothing)
    End Sub
End Class

Sharplab.io

It's possible that there could be a custom operator defined for ==, which could be slower than a simple pointer comparison. is null reads better and is guaranteed to be just a pointer comparison.

Imo, if the user has an overloaded operator == then we should be respecting that. I think using "== null" is appropriate for that feature.

also reported here

Could this be implemented and configured using an option in .editorconfig? Autogenerating code increases productivity (and I'm talking not only about this specific code fix, but also about auto-generated constructors), yet if one wants to enforce the is null/is object pattern for null checks in the codebase, it just won't work.
P.S. https://twitter.com/jaredpar/status/1115019017297596416 @jaredpar

Was this page helpful?
0 / 5 - 0 ratings