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 == null
s or is null
s, to see which codefix should be offered to maintain consistency.
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
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
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
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
Most helpful comment
We should change the language to permit
value is null
for an unconstrained generic.