Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Object reference not set to an instance of an object

Posted on 2010-08-16
11
Medium Priority
?
572 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 2
11 Comments
 
LVL 3

Accepted Solution

by:
with earned 2000 total points
ID: 33450656
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
ID: 33450674
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 34

Author Comment

by:it_saige
ID: 33455805
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
 [eBook] Windows Nano Server

Download this FREE eBook and learn all you need to get started with Windows Nano Server, including deployment options, remote management
and troubleshooting tips and tricks

 
LVL 3

Expert Comment

by:with
ID: 33455942
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 34

Author Comment

by:it_saige
ID: 33457059
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
 
LVL 17

Expert Comment

by:nepaluz
ID: 33457158
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 34

Author Comment

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

-saige-
0
 
LVL 3

Expert Comment

by:with
ID: 33457508
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 34

Author Comment

by:it_saige
ID: 33457681
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
ID: 33458938
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 34

Author Comment

by:it_saige
ID: 33459084
> 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

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.
Make the most of your online learning experience.
Six Sigma Control Plans
Introduction to Processes
Suggested Courses

610 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