You need to be careful with the differences between 0, Nothing, and vbNull.
0 is a default value for a Boolean.
vbNull is a reserved Null value which should translate as 1.
Nothing will throw an exception in almost all circumstances.
Dim a As Boolean? = Nothing
Dim b As Boolean? = vbNull
Dim c As Boolean = vbNull
Dim d As Boolean
Print(a = True) 'will throw an Exception
Print(b = True) 'will return True (as vbNull = Int(1))
Print(c = True) 'will return True as the ? is unnecessary on a Boolean as vbNull = Int(1)
Print(d = True) 'will return False as the default value of a Boolean is 0
Print(a.GetValueOrDefault) 'will return False as this handles the Nothing case.
When working with unassigned values you should always check for Nothing first (or just follow good practice and set the value before you use it).
Dim a As Boolean?
Dim b As Boolean = IIf(IsNothing(a), False, a)
This will return False if a is Nothing, otherwise return A.
Only after testing for Nothing can you test for vbNull, as Nothing returns an error on all values. The code below will return False if Nothing or vbNull, or a otherwise.
Dim a As Boolean?
Dim b As Boolean = IIf(IsNothing(a), False, IIf(a = vbNull, False, a))
Note: you cannot use the code below as the test a = vbNull will be against Nothing which will throw an Exception.
Or(IsNothing(a), a = vbNull)
I would also avoid using GetValueOrDefault in any real application, as when you start using more complicated data types the default won't be so simple and you can get unexpected results. It's far better IMHO to test for IsNothing (or Object = Nothing, Object Is Nothing) than to rely on quirks of a datatype.
Best practice would be to ensure a has a value, which you can do using
Dim a As Boolean? = New Boolean()
Dim b As Boolean = a
The reason I say this is the best practice is because it translates to all Classes, not just Booleans. Noted that this is overkill for Booleans.
Hope this helps.