VB.NET Structs and Nothing - problems
-
02-10-2019 - |
Question
I'm having some headaches using Structures and functions that return Nothing in VB.NET.
Let me try to explain here with this code:
Public Class Form1
Structure Test
Dim field1 As String
End Structure
Private Function Foo() As Test
Return Nothing
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim st As Test = Foo()
End Sub
End Class
In the previous code, when I return Nothing as result of Foo function I'd expect that st is Nothing. But this is not what happens.
Then I found in MSDN documentation:
Assigning Nothing to a variable sets it to the default value for its declared type. If that type contains variable members, they are all set to their default values.
So I discovered that when I assign Nothing to a structure, all its members are set to their default values, instead of the struct itself.
Also, I tried to make st a Nullable type by declaring:
Dim st As Nullable(Of Test) = Foo()
but, still I can't check if st is Nothing by using:
If st Is Nothing Then
or
If st.Equals(Nothing) Then
So, questions:
1 - Is it possible to assign Nothing to the structure and not to its members?
2 - How can I check if a return struct value is Nothing?
Solution
A structure is a value type, it cannot be Nothing. The Nullable type can solve your problem, put a question mark after the type name to make it short and snappy. Here's an example:
Module Module1
Structure Test
Dim field1 As String
End Structure
Private Function Foo() As Test?
Return Nothing
End Function
Sub Main()
Dim st As Test? = Foo()
Debug.Assert(st is Nothing)
End Sub
End Module
OTHER TIPS
The first two following methods are used frequently in the .NET Framework. The method you use will depend on your requirements. I will use Method #3 if the structure tested infrequently. For frequent testing, I will use Method #1 if Method #2 is not appropriate for "empty" testing. For instance, the Point
structure defines an empty point as {x=0,y=0}, which I do not think is correct. Therefore, I would use the first method in my point structure implementation.
Method 1: Define Empty
Test for Comparison Testing
Add shared Test
to use for an empty-comparison.
Structure Test
Public Shared Empty As Test = New Test
Dim field1 As String
End Structure
Test as:
If st = Test.Empty Then
Method 2: Define IsEmpty
Property for Testing
Define an IsEmpty
property based on the structure's internal state.
Structure Test
Public ReadOnly Property IsEmpty As Boolean
Get
Return Len(field1) = 0
End Get
End Property
Dim field1 As String
End Structure
Test as:
If st.IsEmpty Then
Method 3: Use Nullable(Of T)
Define as:
Dim st As Test? = Foo()
'--or--
Dim st As Nullable(Of Test) = Foo()
Test as:
If st Is Nothing Then
'--or--
If st.HasValue = False Then
Note
I have not tested the above code and I do not have access to my code-library.
Inspiration
Take a look at Microsoft's Point
and Color
structures, using their published source code or using .NET Reflector.
There's no such concept as assigning "Nothing to the structure and not to its members".
It sounds very much like you should be looking at nullable value types and Nullable(Of T)
- if you need to be able to represent the absence of a "real" value for a value type, that's precisely the reason it was invented.
Consider Byte
for example. A Byte
value can have any of 256 values (0-255). If you assign it the value Nothing
, that will actually make it 0. It can't make it "some value not in the range 0-255" as it's going to be stored as a byte. I regard it as somewhat unfortunate that VB does let you use Nothing
here, actually... because philosophically a "missing" value and the value 0 are very different things indeed.
Anyway, nullable value types wrap "normal" value types and provide an extra Boolean value to say whether there's really a useful value present or not.