6

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?

AMissico
  • 21,470
  • 7
  • 78
  • 106
RHaguiuda
  • 3,207
  • 9
  • 37
  • 55

3 Answers3

19

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
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 2
    The ? is short-cut for `Nullable(Of Test)`. – AMissico Jul 02 '10 at 21:05
  • 1
    @Hans Passant: No way, you cheat. My answer is so much better! :O) – AMissico Jul 02 '10 at 21:22
  • Sorry @amiss, this is the kinda question where "just add a question mark" hands the OP the solution. Surely your detailed answer will get many more upvotes than mine over the next 10 years. Better check that IsEmpty theory though. – Hans Passant Jul 02 '10 at 21:40
  • @Hans Passant: Can you go over to http://stackoverflow.com/questions/3169102/how-to-access-a-method-on-an-object-thats-passed-in-as-a-parameter-to-a-generic and make a comment regarding the assignment of a temp variable before calling Invoke and why it is a good idea. From a previous exchange of ours weeks ago, I make have made a technically incorrect comment that caused a flurry of other comments. – AMissico Jul 02 '10 at 22:05
  • @AMissico: dtb is right, the copy of the reference was already made. Same thing as copying it into *handler*. Using the handler pattern is boilerplate until the egg doesn't get cooked the same way. – Hans Passant Jul 02 '10 at 22:55
  • @Hans Passant: Ah, slipped my mind that handler was already assigned. Thank you. – AMissico Jul 02 '10 at 23:21
14

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.

AMissico
  • 21,470
  • 7
  • 78
  • 106
0

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194