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. MartinJ

    It’d be nice if the next version (after Whidbey) made nullable a decoration on the variable declaration (like Overloads and other modifiers). So, you’d do something like:

    Dim x As Nullable Integer

    It would also be nice to be able to hide the "HasValue" function call. So, you could check for a missing value using:

    If x Is Nothing

    -or-

    If x IsNot Nothing

    (I can’t remember if IsNot is the new comparison operator)

    This would be translated as x.HasValue or (Not x.HasValue) internally.

    It would also be nice if the compiler could hide the other conversions as much as possible. I understand that this might cause some issues. Passing these Nullable things around could cause problems when argument types don’t match. Option Strict could catch those potential conversions (from Nullable to ordinary value types might cause weird behavior; the opposite should be fully transparent).

    Granted, I realize that suggesting something like this has probably already been considered. But, you can add my vote for this.

    Reply
  2. Mike Schinkel

    We are currently calling classes compiled in VB.NET 2003 from ASP code, and if I understand your "nullable" correctly, we could really use it. Right now, if we call a method with a parameter that is not exactly the right data type it will crash without a very good error message. The only option is to make all parameters to be type object, which is yuck. So we have to type-cast ever method call we make in ASP, which is also yuck. Of course I don’t know how much value there will be in general for interfacing with "legacy" technologies like ASP, but it is one data point that agrees with the value of having nullable value type parameters.

    Reply
  3. Eric Mutta

    I can’t say I’ve fully digested what is trying to be achieved with this feature, but the sound of "null propagation" returns some stomach churning memories from nulls in VB6 variants, while the idea of nullable value types (NVT) screams out "NullReferenceException".

    Some questions:

    *what happens when you operate on an NVT with the value Null?

    *do NVTs affect a procedure’s signature in overloading?

    *can NVTs result in aliasing like with reference types?

    *how much overhead does Nullable(Of T) have over plain T?

    I dunno about others, but when working with DBs over the past 2yrs I found that finding other techniques to indicate missing data was easier than allowing Null. For instance, with null propogation, writing a query to sum up the salaries paid to all employees would return Null even if its only one employee who wasnt paid a salary (and hence had Null in the salary field of their record). One would have to adjust the query to filter out null values, which in the case of the retired employee example, is not too different to disallowing nulls then dealing with it by filtering out retired employees in certain salary calculations.

    I trust you guys know what you are doing, but I have a rather bad feeling about the ramifications of this feature.

    Reply
  4. Pingback: Code/Tea/Etc...

  5. paulvick

    Eric: Yes, people seem to either love or hate nulls. As it stands for VB, this will just be another type, but as we integrate it more into the language, we are mindful of the ramifications (as are the C# team). In terms of your questions:

    * You have to convert a NVT to the actual value type before using methods on it. If the NVT is null, converting it to the actual value type will throw an exceptions.

    * NVTs are distinct types, so they participate in overloading as such. There exists a widening conversion from T to Nullable(Of T), so we’ll always choose T as the more specific type.

    * No, NVTs cannot alias.

    * The overhead is up in the air at the moment. The JIT team is looking at how to best optimize them. We will likely be doing some work in VS 2005 and then more as time goes on.

    Reply
  6. Mike Gale

    This is the first tranche of the features mentioned in "Unifying Tables. Objects and Documents" by Meijer and Shulte. Ken Levy said that X# is dead and they go into the CLR.

    I’m really keen to see the other features streams (!, +, ?, *), tuples, unions, content classes and queries implemented in full. Then we can really start getting way from the impedance mismatches caused by type limitations.

    Are those features (in VB.NET) likely in CLR 2.x or are we looking at a 3.0 time-frame?

    Reply
  7. paulvick

    Since the CLR 2.0 = VB 2005, we won’t be doing anything with them in this next release. Beyond that, we’re looking at the ideas, but there are no definite plans.

    Reply
  8. Mark Hurd

    I hope that C#’s boolean expression choices won’t cause the null propagation of VB.NET v.whatever to be any different to the three-valued logic that VB?-VB6 used with Null mostly corresponding to "Maybe".

    Reply
  9. Pingback: VS Data Team's WebLog

  10. Pingback: VS Data Team's WebLog

  11. Shaun

    VB.NET really could use this. I feel that VB.NET is the most English-like and clear OOP language on the face of the planet.

    It would be nice to see more focus on features like this which are handy for building frameworks rather than things like the My namespace (shutter).

    I know that a lot of people griped about VB.NET being "hard" or "too complicated" … frankly, it seperated the men from the boys and was the best thing to ever happen to Visual Basic.

    I’d love to see MS treat VB.NET like the realy grown-up language that it is in Orcas.

    Reply
  12. Pingback: Sven's Blog

  13. orbit

    I get an InvalidCastException when trying to assign

    Dim salary As Nullable(Of Short) = CType(row.Item("salary"), Global.System.Nullable(Of Short))

    when row.Item("salary") equals System.DBNull.Value

    Am I missing something?

    Reply
  14. Pingback: Frans Bouma's blog

  15. Pingback: Frans Bouma's blog

  16. Pingback: Paul Wilson's .NET Blog

  17. Pingback: Dennis' blog

  18. Peter

    Hi Paul.

    I know its an old topic by now but I still don’t understand the reason for having nullable types in VB 2005.

    Ok, its nice to be able to check wether a variable that might be empty has a value at all but how do I asign a value to a nullable variable that might be null, like:

    Dim Nulli As Nullable(Of Integer)

    Nulli = Ta.Rows(0).Item("Wert2")

    If the field Wert 1 in Ta Row #1 is actually Null I get an invalidcast exception.

    So what is the nullable type good for?

    Please explain this,

    Peter

    (loyal vb programmer)

    Reply
  19. paulvick

    Peter,

    Ideally, nullable would be used everywhere, so that the item you were looking up would be nullable as well, so the nulls would propagate throughout the system. Nullable types are useful for representing the absence of a value instead of just a zero value (i.e. "I didn’t specify an integer here. It’s blank.").

    Reply
  20. Pingback: Patrice 's Blog

  21. Pingback: Patrice 's Blog

  22. Albert

    Thanks so much, I like C# but I miss my pointers so much to handel this damm null in variables.

    In Memory to int*, that can be null. πŸ˜‰

    Reply
  23. Pingback: ?????

  24. Pingback: M.A.I.Q.I. 's Blog

  25. Pingback: rodiniz

  26. Pingback: Scott Kuhl

  27. Pingback: Absolute Opinion

  28. Pingback: Living .NET...

  29. Pingback: ??

  30. Cameron Beccario

    So VB 2005 has no coalesce operator "??", but at least you can write a handy generic method to give you the same behavior:

    Public Function Coalesce(Of T As Structure)(ByVal x As Nullable(Of T), ByVal y As T) As T

    If x.HasValue Then Return x.Value

    Return y

    End Function

    Then you can use it like this:

    Dim a As Nullable(Of Integer) = Nothing

    Debug.WriteLine(Coalesce(a, -1))

    And if you need to coalesce three values (or more), you can just add more overloads:

    Public Function Coalesce(Of T As Structure)( _

    ByVal x As Nullable(Of T), _

    ByVal y As Nullable(Of T), _

    ByVal z As T) As T

    If x.HasValue Then Return x.Value

    If y.HasValue Then Return y.Value

    Return z

    End Function

    Reply
  31. Pingback: D.Dogaja

  32. Pingback: random ramblings....

  33. Pingback: qdzx2008

  34. Nancy Nullable

    Nullable syntax Just Polluted the language.

    Pretty soon you are going to see the following:

    int#=10;//Integer to hold house numbers(US only)

    int%=20;//Integer to hold percentage values

    int- =5;//to hold negitive values

    String@="name@name.com";//String to hold emails

    It just sucks.

    Reply
  35. Mike

    I don’t know why you VB programmers don’t just take the plunge into C#. VB.NET will forever be two steps behind and you’ll be whinging for a long time how this and that feature aren’t properly supported etc. C# is SO simple and elegant. I think you guys must be massochists! VB is ugly compared to C#, this is a fact. It’s like writing an essay instead of making a program. With C# the language melts into the background and you barely notice it at all. With VB it’s all in your face. It’s like one of those dreams where you’re running as fast as you can but don’t seem to be getting anywhere. Get your stupid fat heads around it, bite the bullet, drop the horrible baggage that comes with VB.NET and learn a proper programming language for God’s sake. Name one thing that VB.NET does better than C#.

    Reply
  36. Code Goober

    Mike…you’re like the last guy to hear the rumor roaming about the classroom. The time and place for this argument is well past. There really aren’t any major features that make either language clearly superior. Get over it and get out a bit…that yellow orb in the sky is the sun…don’t be afraid.

    Reply
  37. ProJee

    hello :){{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}

    this was masochism, not VB.NET πŸ™‚

    Reply
  38. Pingback: Living .NET...

  39. Pingback: ?????

  40. Pingback: iwainfo

  41. Pingback: iwainfo

  42. Pingback: jelink

  43. Pingback: ?????

  44. Pingback: Duncan Mackenzie .Net

  45. Pingback: ????

  46. Developed-r

    Why not forget about some symbol that represents nullable, just make it nullable and take care of it like in Java or C?

    I like those last comments, they’re funny! I thought the arguement was Java/C vs. VB/C# !

    Reply
  47. Pingback: ???

  48. Zisha

    Nullable Types are useful in VB until you actually try to use them.

    Try comparing them – If n1 = n2 and you get "Operator = not defined…." ok ok you can do n1.Equals(n2) but what about > and <

    Reply
  49. Pingback: heker2007

  50. 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
  51. Pingback: LeeLin

  52. 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
  53. 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
  54. 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
  55. 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
  56. 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
  57. 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