Although this is probably not a proven fact, the most common error that one can receive while
programming in .NET is probably the System.NullReferenceException. This can be frustrating, especially
as code gets complicated and lots of class references are being used.
The first thing to note: Classes pass references amongst themselves, while structures pass all of their
data to other structures.
To illustrate the points above as well as other points, I'll draw some pictures (aren't pictures beautiful?).
So, here we have two Bipole types - the only difference is that one is a structure, the other is a class.
Public Structure BipoleS
Public Number As Integer
Public Label As Char
Public Sub New(ByVal L As Char, ByVal N As Integer)
Me.Label = L
Me.Number = N
End Sub
End Structure
Public Class BipoleC
Public Number As Integer
Public Label As Char
Public Sub New(ByVal L As Char, ByVal N As Integer)
Me.Label = L
Me.Number = N
End Sub
End Class
Next, I declare 5 of the Structures and 5 of the Classes.
Dim Alpha, Beta, Delta, Gamma, Epsilon As BipoleS
'Structures!
Dim Jupiter, Saturn, Uranus, Neptune, Pluto As BipoleC
'Classes!
Depicted in this picture:
The five classes all have blue lines leading from them... they are all leading to the gray region on the side. This gray region
will hold all class instances that have been created. Of course none have been created so far, so this area is empty. When one is
created, it will be placed in this gray region. So, at the moment, all of the 'planets' are null references, throwing a NullReferenceException
if you try access their Number or Label. The structures, however, require no references, so they have been initialized to have character zero (represented by
the tiny X in the upper left corner of the square) and an integer with 0 inside... so all of the 'greek letters' have values inside.
So, I can set values to the Structures now if I desire to:
Alpha.Number = 18
Beta.Label = "Z"c
Delta.Number = 8
Delta.Label = "&"c
Epsilon.Label = "w"c
Epsilon.Number = Alpha.Number
'Set a few properties for the structures.
They set themselves accordingly:
Assigning a structure to another structure means that everything in the structure is copied over into the new structure.
Gamma = Delta
Also, we can use the constructor to set up a structure. (The constructor is very much like a function even though it is listed as a 'Sub'... in the fact
that it does return a version of this structure... but you cannot change what it returns)
Alpha = New BipoleS("+"c, 49)
Of course, our Structure contains more members than Number and Label. .NET gratuitously adds five other methods
(Equals, GetHashCode, GetType, ReferenceEquals, and ToString) to our structure.
Equals should be self-explanatory: it checks if all member variables are equal. The other Equals (the shared one) is one from
the underlying object class. ReferenceEquals is also a method of the underlying Object class (because a Structure is an object), but since
Structures are not tracked by reference, ReferenceEquals will always return False.
If Object.ReferenceEquals(Delta, Gamma) Then 'this is false because these are structures.
If Object.ReferenceEquals(Delta, Delta) Then 'even this is false.
GetHashCode would probably be useful in a HashTable (haven't used it yet, but soon).
ToString returns a pretty useless string ("ConsoleApplication4.Module1+BipoleS" for me) unless you override ToString in the structure.
GetType returns a Type class object... this is helpful for determining the type from an object.
Now, let's look at the classes.
First step, of course, is to create a new instance of BipoleC. Right now, we'll get a NullReferenceException accessing either planet's Number or Label.
Saturn = New BipoleC("i"c, 4)
Now, we've created a New version of BipoleC, and then set Saturn to reference this New version.
A few more references:
Jupiter = New BipoleC("/"c, 50)
Pluto = New BipoleC("%"c, -5)
Uranus = New BipoleC("J"c, 71)
Now, the only reference that will give us a NullReferenceException is Neptune.
I'll assign Uranus's reference to Neptune.
Neptune = Uranus
Now, all of the planets have been set to an instance. No NullReferenceExceptions here, and all four of the instances are associated with one of the
references. Now, let's assign Saturn to something else.
Saturn = Uranus 'The same as Saturn = Neptune.
Note that the instance containing i and 4 is now gone. The instance will eventually be destroyed by the garbage collector.
Setting values on Saturn, Uranus, or Neptune will change the values of the J 71 box now.
Neptune.Label = "A"c
Saturn.Number = 12
Now, let's kill some references:
Pluto = Nothing 'Severing the tie between Pluto and the % -5 instance.
At this point, the i 4 instance and the % -5 instance are unlinked, which means they'll be picked up the garbage collector at any moment. Also, I'll
get a NullReferenceException accessing Pluto's Label and Number.
Saturn = Nothing 'Sever connection with Saturn.
Uranus.Number = 11 'No NullReferenceException
Uranus = Nothing
Neptune.Number = 10 'No NullReferenceException
Have fun with classes and structures!