Every once in awhile, you come across this exception:
System.NullReferenceException â âObject reference not set to an
instance of an object.â You see people asking about this
everywhere; about why are they getting this error. Below are a
few common causes for this.
1. In VB.Net, you are trying to access a string
that has not been initialized. In C#, this isnât possible.
You canât even compile code like the following in C#
C# won't compile this
privatevoid TestString()
{
string a;
if (a.Length == 0)
{
Console.WriteLine("Yes");
}
}
However, in VB.Net, you can compile the equivalent, and that lead right down a road to the mentioned exception.
VB will compile, but throw a runtime exception.
PrivateSub TestString()
Dim a AsString
If a.Length = 0 Then
Console.Write("Yes")
EndIf
EndSub
Remember, a string is a reference type (a character array) that has
to have a value. You donât have to use the ânewâ keyword, but by
default the value is Nothing/null. You would have to at least
initialize to a = String.Empty, or to some other actual value, before
it will compile in C#, or run without exception in VB.Net
2. You never created a new instance of an
object. Again, this is code that C# will not compile, but VB.Net
will, and throw a runtime error. Same as a string, any reference
type must be initialized. Strings, DateTimes and some other CTS
types have a misconception of being value types, like Integers, and
they are not.
C# will not compile.
privatevoid TestObject()
{
ArrayList b;
b.Add("Hello");
}
Here is the VB equivalent, that will compile, but throw the mentioned exception.
VB will compile but throw an exception.
PrivateSub TestObject()
Dim b As ArrayList
b.Add("Hello")
EndSub
3. You created the object, but killed it too soon. Here is a simple example of that.
Don't kill objects too soon.
PrivateSub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Load
TestObject()
ShowCount()
EndSub
Dim b AsNew ArrayList
PrivateSub TestObject()
b.Add("Hello")
b = Nothing
EndSub
PrivateSub ShowCount()
Console.Write(b.Count.ToString())
EndSub
A more complex example would be that you disposed of a class that
maybe you use to access the database. This killed the connection
and command objects. But then, somewhere else, you tried to call
a method of that class that used those objects that no longer
exists. Again, same exception gets thrown, but coming from
withing the instantiated class itself.
c = a.GetOrders() will throw an exception.
PublicClass Class2
Dim a AsNew MyDataAccessObjects.Customers
PublicSubNew()
LoadData()
LoadMoreData()
EndSub
PrivateSub LoadData()
Dim b AsNew Collection
Try
b = a.GetCustomers()
Finally
a.Dispose()
EndTry
EndSub
PrivateSub LoadMoreData()
Dim c AsNew Collection
Try
c = a.GetOrders()
Finally
a.Dispose()
EndTry
EndSub
EndClass
The GetOrders function inside of Customers requires an instance of a
connection, but you disposed of the required objects required to access
the database back up in LoadData() when you called a.Dispose().
Be careful when you clean up your instances, that you are not using
them again somewhere. This is most common in classes where you
are using class-wide instantiated objects. If you create and drop
your objects within each method, this isnât going to be a problem, and
you are actually following a better guideline by creating at the last
necessary moment, and destroying at the first possible moment, not to
mention avoiding possible exceptions like InvalidReferenceException.