Solved

Object reference not set to an instance of an object

Posted on 2010-08-16
11
545 Views
Last Modified: 2013-11-27
Hey All,

I have a wee bit of a problem.  Let me start by explaining the goal of this code.  The goal is to fill a pair DataGridViews (pOrders and cOrders) in one of my forms with information from a database.  Simple.

But I am running into a problem.  Suprisingly, I have not even gotten to the point of putting data into the GridView.  My problem is occuring when I am trying to fill the Generic.List(Of SomeType) with data that I get the error message.  I have looked at the scope to make sure that the issue is not there (made the object reference public and so forth).  Below is the code I have.  I would be grateful for any assistance that can be provided.

The error itself takes place in the RefreshPendingOrders and RefreshCompletedOrders Subs.  When I try to add a new OrderItemDetail to the Generic.List(Of OrderItemDetail), I recieve the error 'Object reference not set to an instance of an object'

Again, thanks for any assistance provided.

-saige-
Imports CCRS.Global.Settings.My

Imports CCRS.Global.Settings.My.Resources



Public Class Record

	Private ActiveCustomerID As Integer

	Private AllowCustomerEdit As Boolean

	Private SessionPayments As Generic.List(Of PaymentItem)

	Private pList As Generic.List(Of OrderDetailItem)

	Private cList As Generic.List(Of OrderDetailItem)



	Public Sub ViewCustomerRecord(ByVal customerID As Integer, ByVal allowEdit As Boolean)

		' ----- Provide access to the customer record.

		ActiveCustomerID = customerID

		AllowCustomerEdit = allowEdit

		Me.ShowDialog()

	End Sub



	Private Sub CustomerRecord_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown

		' ----- F1 shows online help.

		If (e.KeyCode = Keys.F1) Then OnlineHelp(Me, "CustomerRecord.htm")

	End Sub



	Private Sub RefreshPendingOrders(ByVal sqlText As String, _

	 ByVal dbInfo As SqlClient.SqlDataReader)

		Dim newEntry As OrderDetailItem



		On Error GoTo ErrorHandler



		' ----- Load in the list of pending orders.

		sqlText = String.Format("SELECT ID, Linker, RecordID, oNumber, oDate, " & _

		 "oTime, PONumber, Completed FROM Orders WHERE RecordID = {0} AND Linker = {1} AND " & _

		 "Completed = 0 ORDER BY oNumber", _

		 ActiveCustomerID, _

		 CInt(General.Linker.Customers))

		dbInfo = CreateReader(sqlText)

		Do While dbInfo.Read

			' ----- Add this order to the list.

			newEntry = New OrderDetailItem

			newEntry.ID = CInt(dbInfo!ID)

			newEntry.oNumber = DBGetText(dbInfo!oNumber)

			newEntry.oDate = CDate(dbInfo!oDate)

			newEntry.oTime = CDate(dbInfo!oTime)

			' Error occurs at this line - Object reference not set to an instance of an object

			pList.Add(newEntry)

		Loop

		dbInfo.Close()



		pOrders.DataSource = pList



ErrorHandler:

		GeneralError("CustomerRecord.RefreshPendingOrders", Err.GetException())

		If Not (dbInfo Is Nothing) Then dbInfo.Close() : dbInfo = Nothing

		Return

	End Sub



	Private Sub RefreshCompletedOrders(ByVal sqlText As String, _

	 ByVal dbInfo As SqlClient.SqlDataReader)

		Dim newEntry As OrderDetailItem



		On Error GoTo ErrorHandler



		' ----- Load in the list of completed orders.

		sqlText = String.Format("SELECT ID, Linker, RecordID, oNumber, oDate, " & _

		 "oTime, PONumber FROM Orders WHERE RecordID = {0} AND Linker = {1} AND " & _

		 "Completed = 1 ORDER BY oNumber", _

		 ActiveCustomerID, _

		 CInt(General.Linker.Customers))

		dbInfo = CreateReader(sqlText)

		Do While dbInfo.Read

			' ----- Add this order to the list.

			newEntry = New OrderDetailItem

			newEntry.ID = CInt(dbInfo!ID)

			newEntry.oNumber = DBGetText(dbInfo!oNumber)

			newEntry.oDate = CDate(dbInfo!oDate)

			newEntry.oTime = CDate(dbInfo!oTime)

			' Error occurs at this line - Object reference not set to an instance of an object

			cList.Add(newEntry)

		Loop

		dbInfo.Close()



		cOrders.DataSource = cList



ErrorHandler:

		GeneralError("CustomerRecord.RefreshCompletedOrders", Err.GetException())

		If Not (dbInfo Is Nothing) Then dbInfo.Close() : dbInfo = Nothing

		Return

	End Sub



	Private Sub CustomerRecord_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

		' ----- Prepare the form.

		Dim sqlText As String

		Dim dbInfo As SqlClient.SqlDataReader

		Dim holdText As String

		Dim counter As Integer

		Dim itemID As Integer

		Dim totalCount As Integer

		Dim totalAhead As Integer

		Dim canvas As Drawing.Graphics

		Dim newEntry As OrderDetailItem



		On Error GoTo ErrorHandler



		RecordLastActivity.Text = "Not Available"



		' ----- Load in the customer name. 

		sqlText = String.Format("SELECT C.ID, C.Active, C.LastName, C.MI, " & _

		 "C.FirstName, C.SuffixID, C.SAddressID, C.BAddressID, C.PhoneID, " & _

		 "C.GroupID, C.PTermID, C.Comments, C.AdminMessage, C.LastActivity, " & _

		 "S.ID, S.FullName FROM Customers As C " & _

		 "INNER JOIN CodeNameSuffix As S ON S.ID = C.SuffixID " & _

		 "WHERE C.ID = {0}", _

		 ActiveCustomerID)

		dbInfo = CreateReader(sqlText)



		If (dbInfo.Read) Then

			CustomerName.Text = FormatCustomerName(dbInfo)

			If (IsDBNull(dbInfo!LastActivity) = False) Then _

			 RecordLastActivity.Text = Format(CDate(dbInfo!LastActivity), _

			 "MMMM d, yyyy")

		End If

		dbInfo.Close()



		' ----- Load in the list of pending orders.

		RefreshPendingOrders(sqlText, dbInfo)



		' ----- Load in the list of completed orders.

		RefreshCompletedOrders(sqlText, dbInfo)



		' ----- If the user has authorization, show the Edit Customer button.

		If (SecurityProfile(CCRSSecurity.ManageCustomers) = True) Then

			' ----- If this form was called ultimately from the edit customer form,

			'       then hide the Edit Patron button.

			ActEditCustomer.Visible = AllowCustomerEdit

		Else

			' ----- This user is not authorized to edit customer records.

			ActEditCustomer.Visible = False

		End If



		Return



ErrorHandler:

		GeneralError("CustomerRecord.CustomerRecord_Load", Err.GetException())

		Resume Next

	End Sub



	Private Sub ActClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ActClose.Click

		' ----- Print out a ticket if needed.

		If (SessionPayments.Count > 0) Then _

		   PrintPaymentTicket(ActiveCustomerID, SessionPayments)

		SessionPayments.Clear()

		SessionPayments = Nothing



		' ----- Close the form.

		Me.DialogResult = Windows.Forms.DialogResult.Cancel

	End Sub

End Class

Open in new window

0
Comment
Question by:it_saige
  • 5
  • 4
  • 2
11 Comments
 
LVL 3

Accepted Solution

by:
with earned 500 total points
Comment Utility
Hi saige,

Try changing lines 8 and 9 of what you posted to include the New keyword,
Private pList As New Generic.List(Of OrderDetailItem)
Private cList As New Generic.List(Of OrderDetailItem)

Open in new window

0
 
LVL 17

Expert Comment

by:nepaluz
Comment Utility
How do you declare your Generic.List(Of OrderItemDetail)?
Since you do not include the declaration, my first port of call would be to make sure thatit is as below:

Dim YourList As New List(Of OrderItemDetail)

The NEW is rather important, the lack of which WILL throw an error like yours.
0
 
LVL 32

Author Comment

by:it_saige
Comment Utility
Ok I used the New keyword in both of my declarations and viola, the data is now put into the lists.  I guess I still don't completely understand when to designate the New keyword.  :(

Thanks for your help.

-saige-
0
 
LVL 3

Expert Comment

by:with
Comment Utility
When you Dim an object type in VB.NET, think of that variable as being something that "could" point to an object in memory, but one that does not point to anything *yet*.  It does not yet "reference" an actual object in memory.

Btw, that's why the error message is, "Object reference" (i.e., your variable pList is the "reference") "not set to an instance of an object".  That's the compilers way of telling you, "hey, I went up to pList in memory but... nothing was there!?"

The New keyword is your way of constructing a "new" (hence the name) tangible, real List object in memory; the list is empty of items of course, but the List's "Add" method and soforth are now available via the pList reference variable.  

Prior to using the New keyword, pList knows what *Type* of object it could point at (List(Of T)), but prior to using the New keyword it doesn't point to a real one yet.
0
 
LVL 32

Author Comment

by:it_saige
Comment Utility
Interesting...  Makes more sense now...

However, its funny how sometimes you get the reference methods without specifying new but only to find out at runtime that the object reference is invalid...

At other times, during the code writing intellisense lets you know that the object reference is invalid...

And yet still, you can have compile time errors that the object reference is invalid...

In my particular case, I was getting nothing during the writing or compile time with regards to the objects reference (from my point of view, I declared and referenced the object fine)...  It was only during runtime when the method was called that the object reference error occured (thank god for error trapping ;) )...

Do you have any articles or best practices that can be used or reference with regards to using the New Keyword (most of the time, I depend upon intellisense to let me know when I need to use the New keyword), but I would rather like to *know* without depending upon intellisense.

Thanks,

-saige-
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 17

Expert Comment

by:nepaluz
Comment Utility
you can set up the types of warnings you need from the project properties - compile page.
If you have disable all warnings checked, then the compiler will happily follow your intructions.....
0
 
LVL 32

Author Comment

by:it_saige
Comment Utility
I do not have disable all warning checked.  I *want* to know when errors occur. ;)

-saige-
0
 
LVL 3

Expert Comment

by:with
Comment Utility
Yea, I don't like to disable warnings either :)

The compiler is pretty smart, but typically it's intelligence is confined to a certain scope, like a single Sub or a Function.  For example,

Sub MySub
    Dim myList List(Of Integer)
    myList.Add(1)
End Sub

Here I've failed to use New, so "myList" is an "object reference not set to an instance of an object".  To the compiler, it's pretty obvious this code will break. It can see that myList was defined inside MySub, so logically no other Sub or Function can access myList directly.  Therefor it's not possible for any external code to make myList New prior to the myList.Add attempt.

Your post was a just slightly more complex because you're using List objects defined *outside* the scope of the Subs they're used in.  Things just got a lot more complicated for the compiler because any Sub or Function in the Class *could* use the New keyword (or the opposite - set it back to Nothing!) so these variables when used in a Sub "could be anything", as far as the compiler is concerned.  So when things get to complicated, PlanB for the compiler is to give you the benefit of the doubt, and leave you alone.

A basic understanding of how "reference types" work should lead to an intuitive understanding of when to use the New keyword.  Unfortunately I don't have any good articles :\  If you Google around or start a question, what you want is a good VB.NET tutorial explaining Reference Types vs. Value Types.
0
 
LVL 32

Author Comment

by:it_saige
Comment Utility
I think I get it now...

For my understanding.  If, lets say, I would have passed the list to the Sub or Function in question, the Sub or Function in question would depend upon the declaration of the object specified in the class in order to use the object.  As far as the compiler would then be concerned the Class would then need to instansiate the object with the new keyword and the compiler would then spit out a message with regards to that fact.  However, since I did not pass the list to the sub or function the compiler now says that my use of the object is depended upon my instansiation of the object within the sub or function or even outside of the sub or function by way of another method that instansiates the object.

As far as the compiler or intellisense is concerned, I have declared everything correctly because I could always rescope the object to a child method.  Am I following you correctly?

-saige-

0
 
LVL 3

Expert Comment

by:with
Comment Utility
That's about right, maybe just overestimating the compiler's ability to read your code a little bit now.  Passing the reference won't improve the compilers knowledge in regards to whether or not the object has been instantiated yet.  The reason for that kinda starts to wade into the deep end of the swamp.  When it comes to null ref warnings, the design-time compiler can't see anything that happens outside the scope of an individual method; it just assumes that anything being passed in was (at some point) New'd up somewhere outside the scope of the method.

Btw I should mention it's perfectly normal, particularly in larger orthogonal systems, to simply ask what you're dealing with before you touch it:

If pList Is Nothing Then
   pList = New List(Of Things)
End If

So it either already was New'd, or, I just New'd it.  Either way, it's New'd.

pList.Add(aThing)

Experiment in a throw away project; make a list, pass it somewhere, make another list, set them equal to each other, add/remove things from the lists and check them both out.  That's another good way to pick up on a lot of this if you're the learn-by-doing type.
0
 
LVL 32

Author Comment

by:it_saige
Comment Utility
> Experiment in a throw away project; make a list, pass it somewhere, make another list, set them equal to each other, add/remove things from the lists and check them both out.  That's another good way to pick up on a lot of this if you're the learn-by-doing type.

Why whatever gave you that idea...  :P

Learn by doing has always served me well...  You make more mistakes than the average bear, but you learn more about how and why things work...  The down side of the Learn by doing method is that you don't always produce the most elegant or most efficient code...

-saige-

0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This article will show, step by step, how to integrate R code into a R Sweave document
This is about my first experience with programming Arduino.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now