views:

43

answers:

4

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?

A: 

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
A: 

but, still I can't check if st is Nothing by using:

If st Is Nothing Then   

To check if a nullable type has a value, use st.HasValue.

GSerg
+2  A: 

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
@Hans: It works!!! What is this question mark?
RHaguiuda
The ? is short-cut for `Nullable(Of Test)`.
AMissico
@Hans Passant: No way, you cheat. My answer is so much better! :O)
AMissico
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
@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
@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
@Hans Passant: Ah, slipped my mind that handler was already assigned. Thank you.
AMissico
A: 

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