boxing of nullalbe types (changes since Beta 2)

 


Last night I was chatting with Corrado Cavalli about the nullable type changes since Beta 2.  He was kind enough to run some test code for me using the August CTP.


 


The changes to the boxing behaviour mean that when a generic nullable type is boxed, if the nullable type .HasValue is False, then the boxed variable becomes an actual null reference.  If the value is not null, then it can be directly cast to the underlying type or the Nullable type.  for example:


 


Sub Main()


    Dim x as New Nullable(Of Int32)


    BoxTest(x)  ‘call 1


    x = 42


   BoxTest(x)  ‘ call 2


End Sub


 


Sub BoxTest(ByVal value As Object)


  If value Is Nothing Then Debug.Print “value is Nothing”


  If TypeOf value Is Int32 Then Debug.Print “value is Int32”


  If TypeOf value Is Nullable(Of Int32) Then Debug.Print “value is Nullable(Of Int32) “


End Sub


 


The above test would print out “value is Nothing” in the first case which is when HasValue = False.  In the second case when the nullable type has a value, it prints out both “value Is Int32” and “value is nullable(Of Int32)”


 


So the good news is this simplifies the code a lot.  The INullableValue interface which was introduced in .NET 2.0 purely for Nullable(Of T) to be able to be used from non generic methods is now no longer needed, and hence it’s actually been removed.  Alas poor InullableValue.. R.I.P. smile


So code that would have looked like:


Sub BoxTest(ByVal value As Object)


  If TypeOf value Is INullableValue Then
     If CType(value, INullableValue).HasValue Then
         …
     End If
  End If

Now just becomes:


Sub BoxTest(ByVal value As Object)


    If value IsNot Nothing Then


 


And the other nice bit now comes into play, that is , being able to treat the boxed nullalbe type like it’s internal type.  That means you can treat a Nullable(Of Int32) the same as an Int32.  So if for example today you already have code that deals with a value as Object, and you then determine it’s type, checking for intrinsic types, well the good news is that code will work with the nullable types without any modification. e.g.


 


Sub WriteValue(ByVal value As Object)


   If value Is Nothing Then return  ‘ early exit


   If TypeOf value Is IConvertible then


      Select Case CType(value, Iconvertible).GetTypeCode


             Case Typecode.Int32



             Case Typecode.Byte



etc…


 


So that code will work fine with nullable types.


 


The big disappointment I have with the approach taken though is that although the Null checking has been made simpler, the value type semantics has been broken, and hence information is lost.  When you define a Nullable(Of T) type, such as Dim x as New nullable(Of Int32), even though the nullable type has no value at this point of time, it does have an generic parameter type information.  So we have a null value AND information as to the type of the non null value.  It’s the inner type information that is lost when boxed, as a null reference (Nothing) has no type information.


So to me, although I can see some goodness in these changes, it still feels like a hack.   If I want to have null values while preserving the type information, I have to use generic parameters throughout.