Req24: warnings where "Nothing" isn't null

[This post is part of a series, "wish-list for future versions of VB"]

 

IDEA: Emit a warning where "Nothing" is used in a likely-incorrect way. 99% of users think that "Nothing" means the same as C#'s "null", i.e. a null reference or empty nullable -- but it isn't. Nothing is instead the same as C#'s "default(T)". Also, 99% of users don't realise that VB does null-propagation for all operators including the equality operator. We should give warnings in cases where we're overwhelmingly sure that Nothing is being misused.

 

Example 1.

Dim x As Integer? = If(False, 1, Nothing)

' gives x.HasValue=True, x.Value=0

It's hard, though, to know exactly what conditions would trigger the warning. One example condition, which would catch the above case, is "Warn when Nothing means the same thing as the number 0, since the user should have just written 0 instead".

 

Example 2.

Dim x As Boolean? = Nothing

If x = Nothing Then Console.WriteLine("is nothing")

' doesn't print anything

Contrary to common expectations, this code doesn't print anything. The condition we could use to catch this is, "Warn when the user writes an equality operator expr = Nothing or Nothing = expr in the case where expr has nullable type." And indeed in VS2010 we already did introduce this warning!

 

Example 3.

Private _AccessLevel As Integer?

Public Property AccessLevel As Integer?

    Get

        Return _AccessLevel

    End Get

    Set(ByVal v As Integer?)

        If _AccessLevel Is Nothing OrElse _AccessLevel <> v Then _AccessLevel = v

    End Set

End Property

AccessLevel = 15

AccessLevel = Nothing

Console.WriteLine(AccessLevel)

' prints 15: the second assignment didn't do what we expected

In this case the user has written the wrong conditions inside the property setter. The condition we could use to catch this? I don't know. It's not clear. But note that in this case the expression "_AccessLevel <> v" has type Boolean?. Bill McCarthy suggested that we emit a warning whenever a comparison operator (<, >, <>, =) produces a Boolean? but is used in a conditional statement that expects just a Boolean. It's a clever idea but I worry it will have too many false positives.

 

 

Other ideas. One possibility is to add two new keywords to VB, "null" and "default(T)" like in C#. Then we could deprecate "Nothing". This would be a bit of a shame in some cases, though, e.g.

    Sub f(Optional ByVal x As IntPtr = Nothing)

    void f(IntPtr x = default(IntPtr))

But in general, we think that throwing in extra keywords which do almost the same as existing keywords is a bad idea (witness the current confusion over CType vs DirectCast vs TryCast vs CTypeDynamic). We would also not want to deprecate a code construct that's used in 99% of user projects out there.

 

 

Provisional evaluation from VB team: Adding extra warnings is a good idea. We're not sure we've figured out exactly the right conditions that would trigger the warnings, though. We worry that the conditions above will produce false positives, i.e. they will warn in perfectly legitimate code. We also worry that they will produce false negatives, i.e. they will fail to detect cases that should be caught.

If you have been burnt by "Nothing" not being null, please post with your code snippets. That will help us evaluate whether our conditions are appropriate. Thanks!