The Truth about Nullable Types and VB…

There’s been a little confusion about how VB’s going to handle nullable types in VB 2005, so let me try and amplify a little bit on the entry on the VB team blog.

What are nullable types?

One of the primary differences between value types such as Integer or structures and reference types such as Form or String is that reference types support a null value. That is to say, a reference type variable can contain the value Nothing, which means that the variable doesn’t actually refer to a value. In contrast, a value type variable always contains a value. An Integer variable always contains a number, even if that number is zero. If you assign the value Nothing to a value type variable, the value type variable just gets assigned its default value (in the case of Integer, that default value is zero). There is no way in the current CLR to look at an Integer variable and determine whether it has never been assigned a value – the fact that it contains zero doesn’t necessarily mean that it hasn’t been assigned a value.

Unfortunately, there are situations where it would be nice for value types to have an actual null state. The most common example is in a type that represents information from a database. Many databases allow columns of any type to contain a null value that means “you didn’t assign a value to this column.” For example, an Employee database might assign null to the Salary column of retired workers, meaning that they no longer have a salary (instead of assigning some magic value like zero to their salary, which might be accidentally confused to mean that they are still working for no money). The fact that the CLR doesn’t support null values for value types can be somewhat painful in this situation and is the reason that we have the System.Data.SqlTypes namespace. But those types do a lot of extra SQL-type stuff. Wouldn’t it be nice to have this for all value types?

The answer to this is yes, and the generics support added in VS 2005 allows us to do it. In VS 2005, we’re introducing a new generic type called Nullable(Of T) that adds nullability to any value type. How it does this is beyond the scope of this entry and is left as an exercise for the reader. But, suffice it to say, it works just fine. Here’s an example:

Sub PrintValue(ByVal i As Nullable(Of Integer))
    If i.HasValue Then
        Console.WriteLine(CInt(i))
    Else
        Console.WriteLine(“Null value!“)
    End If
End Sub

What is C# doing?

From this base level of functionality, C# is taking nullable type support a bit further in VC# 2005. The primary features they’re implementing are:

  • A new type modifier ? that means “nullable.“ So instead of writing “Nullable<int> i;“ in C#, you can write “int? i;“.
  • A “coalesce“ operator ?? that is a quick way of converting a nullable type to a non-nullable type with a default value. So “int x; int? y; x = y ?? 0“ will assign the value of y to x if it is not null, and will assign the value 0 to x otherwise.
  • Lifted conversions. If a type T has a conversion to type U, then the type T? will have a convertion to type U?. This means you can convert an int? to a long? without having to do explicit null checks.
  • Lifted operators. If a type T supports an operator X, then the type T? supports the same operator. This means that you can add two int? values and get an int? value in return without having to do null checks.

Beyond the question of convenience, the last point means that nullable types in C# will support null propagation semantics. If you add two int? values and one of them happens to be null, then the result of the addition is going to be null. The one place where they break this is for comparison operators – unlike a language like SQL, comparing two nullable types is always going to result in a bool value, not a bool? value. I understand why they’re doing this, but it is an unfortunate thing to have to do.

What is VB doing?

Very unfortunately, nothing will be done in VB 2005 beyond what’s already supported by the Nullable type. We would very much like to support features along the lines of what C# is doing (although I don’t think you’ll ever be writing “Dim x As Integer?”), but nullable types were introduced into the BCL too late in the product cycle for us to be able to add extra features this time around. It’s very disappointing, to say the least, but we do look forward to adding more support in the future. (One interesting point is that it is likely that VB will be able to preserve null propagation when lifting comparison operators because we have two comparison operators. Score another point for Is vs. =.)

This isn’t to say that Nullable types won’t be very useful in VB – just that some extra niceties you’ll get in C# will be, um, temporarily unavailable. May we suggest while you’re waiting that you enjoy the other fine features of our language?

63 thoughts on “The Truth about Nullable Types and VB…

  1. Pingback: heker2007

  2. Gabe

    Nullabel types are useful in VB until you actucally use them, whithout knowing what you are doing.

    all you have to do to compare is to get the .value property. however, if the value has not been set you will get an exception, so if there is a chance it is not set you can call .GetValueOrDefault.

    oh yeah RTFM!

    Reply
  3. Pingback: LeeLin

  4. Darin

    Am I the only one that finds it odd that VB.NET deprecated all the variable type specifiers (like $, !, #, %, &) and now appears to be interested in bringing them back (the ? to indicate a nullable type)?

    Seems to me that the tack should be either to declare type spec chars either wrong, or right and support them thusly.

    Personally, I like them, but I can do without them. Bringing back one, even if it’s to indicate nullable, just seems, well, questionable.

    Just a thought

    Reply
  5. BrianPos

    I use both vb.net and c# on a daily basis (vb.net due to migrated codebase) and find that both are pretty much the same in terms of expressiveness. They both end up as IL at the end, so is really just a syntax now. You can write really bad code in vb.net or c#, and you can also write good, clean code in both too.

    All types are indeed Objects, however the difference is noticed when value types (like int) or reference types (like Control) are used. From my understanding, the nullable generic implemmentation on value types does not incur any boxing/unboxing, which would happen if you shoved it in an object variable.

    So it comes down to value types cannot be null by definition. Changing that would make a whole lot of stuff break, like interop/marshalling/serial comms etc.

    I like the way its done, but think the DBNull stuff should have been better handled, but it was there in 1.0 (or 1.1 can’t remember) before generics, and nullable, appeared. So maybe in future this could be addresses somewhere. In the meantime, we use conversion methods to put the db fields into our properties (via a code generator) so is not such a big problem.

    Brian

    Reply
  6. Anonymous

    When will MS and vb team put more time in vb so that it stays at least the level of c#? When ever new feature is added in .net, it is implemented in c#. and in vb? It is implemented partially. What about the support for lambda, anonymous delegates, nullable types etc?

    Reply
  7. daniel

    Your C# code

    “int x; int? y; x = y ?? 0”

    VB equivalent

    Dim x As Integer : Dim y As Nullable(Of Integer) : x = IIf(y.HasValue, y, 0)

    Reply
  8. Meta-Knight

    daniel: That’s the VB8 equivalent. VB9:

    Dim x As Integer
    Dim y As Integer?
    x = If(y, 0)

    I didn’t put colons because it’s just stupid to put all on this on the same line, even in C# 😉

    Reply
  9. Rahim Surani

    if you define a Nullable variable so you do not required to check if HasValue method you may also call .GetValueOrDefault(defaultvalue)

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *