By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,445 Members | 3,172 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,445 IT Pros & Developers. It's quick & easy.

Classes vs. Structures (Object reference not set to an instance of an object)

P: n/a
I am trying to change some Structures to Classes. The Classes now
look like this ...

Public Class OneAttr
Public AttrName As String
Public Column As String
Public Caption As String
End Class

Public Class OneTable
Public ObjectName As String
Public TableName As String
Public NextIndex As Integer = -1
Public Attrs() As OneAttr
End Class

Public Class Product
Public ProdCode As String
Public NextTableIndex As Integer = -1
Public AtTables() As OneTable
End Class

I made the change, by the way, because I could not do the
initialization of the two fields you see initialized above when I was
using Structures.

But now I get an "object reference not set to an instance of an
object" Many, many hits in Google (this seems to be .Net's favorite
error message) but none were helpful.

Here's the code ...

Dim ThisProd As New Product
ThisProd.NextTableIndex = -1
....

If line.IndexOf("*OBJECT: ") = 0 Then
ThisProd.NextTableIndex = _
ThisProd.NextTableIndex + 1
TI = ThisProd.NextTableIndex 'shorthand
InTable = True
ReDim Preserve ThisProd.AtTables(TI)
ThisProd.AtTables(TI).NextIndex = -1 '< Error
ThisProd.AtTables(TI).ObjectName = _
line.Substring(9).Trim(" "c)

The error occurs on the statement which reads:
ThisProd.AtTables(TI).NextIndex = -1

This code worked when I was using Structures. TI is 0, so I think
that I have created the 1st element of ThisProd.AtTables().

I'll appreciate any and all help, pointers, or sympathy.

Thanks, Bob

Nov 21 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a

Well, it finally occurred to me that I should add Redim and Class to
my Google search. And one of the hits I got suggested to me that
maybe I should add this statement ...
ThisProd.AtTables(TI) = New OneTable
following the Redim. That does seem to have fixed the problem. But I
sure don't see why this statement should be needed when I use a Class
and not needed when I use a Structure.

Can anyone explain?

Thanks, Bob
On Sun, 20 Feb 2005 17:24:15 -0500, eBob.com
<eB******@totallyfakeisp.com> wrote:
I am trying to change some Structures to Classes. The Classes now
look like this ...

Public Class OneAttr
Public AttrName As String
Public Column As String
Public Caption As String
End Class

Public Class OneTable
Public ObjectName As String
Public TableName As String
Public NextIndex As Integer = -1
Public Attrs() As OneAttr
End Class

Public Class Product
Public ProdCode As String
Public NextTableIndex As Integer = -1
Public AtTables() As OneTable
End Class

I made the change, by the way, because I could not do the
initialization of the two fields you see initialized above when I was
using Structures.

But now I get an "object reference not set to an instance of an
object" Many, many hits in Google (this seems to be .Net's favorite
error message) but none were helpful.

Here's the code ...

Dim ThisProd As New Product
ThisProd.NextTableIndex = -1
...

If line.IndexOf("*OBJECT: ") = 0 Then
ThisProd.NextTableIndex = _
ThisProd.NextTableIndex + 1
TI = ThisProd.NextTableIndex 'shorthand
InTable = True
ReDim Preserve ThisProd.AtTables(TI)
ThisProd.AtTables(TI).NextIndex = -1 '< Error
ThisProd.AtTables(TI).ObjectName = _
line.Substring(9).Trim(" "c)

The error occurs on the statement which reads:
ThisProd.AtTables(TI).NextIndex = -1

This code worked when I was using Structures. TI is 0, so I think
that I have created the 1st element of ThisProd.AtTables().

I'll appreciate any and all help, pointers, or sympathy.

Thanks, Bob


Nov 21 '05 #2

P: n/a
Bob,

This is because a struct is a value type and a class is a reference type.
When you say...

DIM myStruct AS myStructType

....You are creating a structure on the heap, like saying ...

DIM myString AS string.

If you DIM something as a class you are actually creating a reference to
that type of object, not creating the object itself. The object is not
actualy created until NEW is encountered. So...

DIM myClass AS myObjectType

.... Does not create an object. In this case myClass will just be a null
pointer, of the correct type. When you say...

DIM myClass AS NEW myObjectType

.... you create a pointer called myClass that referes to a new object of
myObjectType.

Hope that helps,

Dan.

"eBob.com" wrote:

Well, it finally occurred to me that I should add Redim and Class to
my Google search. And one of the hits I got suggested to me that
maybe I should add this statement ...
ThisProd.AtTables(TI) = New OneTable
following the Redim. That does seem to have fixed the problem. But I
sure don't see why this statement should be needed when I use a Class
and not needed when I use a Structure.

Can anyone explain?

Thanks, Bob
On Sun, 20 Feb 2005 17:24:15 -0500, eBob.com
<eB******@totallyfakeisp.com> wrote:
I am trying to change some Structures to Classes. The Classes now
look like this ...

Public Class OneAttr
Public AttrName As String
Public Column As String
Public Caption As String
End Class

Public Class OneTable
Public ObjectName As String
Public TableName As String
Public NextIndex As Integer = -1
Public Attrs() As OneAttr
End Class

Public Class Product
Public ProdCode As String
Public NextTableIndex As Integer = -1
Public AtTables() As OneTable
End Class

I made the change, by the way, because I could not do the
initialization of the two fields you see initialized above when I was
using Structures.

But now I get an "object reference not set to an instance of an
object" Many, many hits in Google (this seems to be .Net's favorite
error message) but none were helpful.

Here's the code ...

Dim ThisProd As New Product
ThisProd.NextTableIndex = -1
...

If line.IndexOf("*OBJECT: ") = 0 Then
ThisProd.NextTableIndex = _
ThisProd.NextTableIndex + 1
TI = ThisProd.NextTableIndex 'shorthand
InTable = True
ReDim Preserve ThisProd.AtTables(TI)
ThisProd.AtTables(TI).NextIndex = -1 '< Error
ThisProd.AtTables(TI).ObjectName = _
line.Substring(9).Trim(" "c)

The error occurs on the statement which reads:
ThisProd.AtTables(TI).NextIndex = -1

This code worked when I was using Structures. TI is 0, so I think
that I have created the 1st element of ThisProd.AtTables().

I'll appreciate any and all help, pointers, or sympathy.

Thanks, Bob


Nov 21 '05 #3

P: n/a
eBob.com wrote:
Well, it finally occurred to me that I should add Redim and Class to
my Google search. And one of the hits I got suggested to me that
maybe I should add this statement ...
ThisProd.AtTables(TI) = New OneTable
following the Redim. That does seem to have fixed the problem. But I sure don't see why this statement should be needed when I use a Class
and not needed when I use a Structure.

Can anyone explain?


I'll have a go :)

Basically a Structure is a value type, and a Class is an object type.
Dry definitions don't help much, so I'll try and elucidate:

When you have a variable of type <some value type>, eg an Integer or a
Point (a structure), that variable always _has a value_. For example,
even if you haven't explicitly set an integer variable to a value, it
already has a value (zero). Same with a variable of type Point. Code
snippet:

Dim i As Integer
If i=0 Then
'this will happen
End If

Dim p As Point
If p.X=0 Then
'this will happen
End If
OK now let's consider variables of type <some object type>, usually
called object variables. Such variables are actually _references to_ an
object; you might like to think of then as signposts; and importantly
they can _refer to no object_, or Nothing in VB.NET syntax. Like a
blank signpost, if you will. And until you explicitly set them to point
at _something_, Nothing is what they point to! Code snippet:

Dim o As Object
If o.GetHashCode()=0 Then 'ERROR!

We get an error because o doesn't refer to any object, so we have
nothing to get the hashcode of! The error we get is in fact 'object
reference not set to an instance of an object', and the reason it's so
common is that uninitialised object variables are a common problem :)

So let's see why you got an error when you switched from Structures to
Classes:
Public Class Product .... Public AtTables() As OneTable
End Class
When OneTable is a Structure (a value type), then each entry in
AtTables is an actual OneTable value - possibly a blank value, but
always a value. When OneTable is a Class, then AtTables is a collection
of _references_, which are references to nothing, until you set them.

So when you get a new line and you want to add a new OneTable:
ReDim Preserve ThisProd.AtTables(TI)
This is fine; we have made room for an extra reference
ThisProd.AtTables(TI).NextIndex = -1 '< Error
The error is because .AtTables(TI) is a null reference, until you make
it refer to something. When OneTable was a Structure, the ReDim
automatically created a new blank _value_; now it is creating a new
_null reference_. As you've discovered, the fix is to do

ThisProd.AtTables(TI) = New OneTable

after the ReDim. Now the reference refers to something, so you can use
it :)
I'll appreciate any and all help, pointers, or sympathy.


There's probably a much better explanation of value types vs object
types in the MSDN somewhere, but hopefully this will get you started.
--
Larry Lard
Replies to group please

Nov 21 '05 #4

P: n/a
It's because classes are reference types and require the New keyword
when instantiating them whereas structures are value types and dont
require that.

Check out these links for additional information. You might also want
to search for articles that explaine value types and reference types in
more detail.

http://www.yoda.arachsys.com/csharp/parameters.html
http://www.yoda.arachsys.com/csharp/memory.html

Nov 21 '05 #5

P: n/a
Thanks to the several responders. I sorta had a vague notion of the problem
but was unable to crystallize it. Thanks, Bob

"Dan Hedges" <Dan He****@discussions.microsoft.com> wrote in message
news:6D**********************************@microsof t.com...
Bob,

This is because a struct is a value type and a class is a reference type.
When you say...

DIM myStruct AS myStructType

...You are creating a structure on the heap, like saying ...

DIM myString AS string.

If you DIM something as a class you are actually creating a reference to
that type of object, not creating the object itself. The object is not
actualy created until NEW is encountered. So...

DIM myClass AS myObjectType

... Does not create an object. In this case myClass will just be a null
pointer, of the correct type. When you say...

DIM myClass AS NEW myObjectType

... you create a pointer called myClass that referes to a new object of
myObjectType.

Hope that helps,

Dan.

"eBob.com" wrote:

Well, it finally occurred to me that I should add Redim and Class to
my Google search. And one of the hits I got suggested to me that
maybe I should add this statement ...
ThisProd.AtTables(TI) = New OneTable
following the Redim. That does seem to have fixed the problem. But I
sure don't see why this statement should be needed when I use a Class
and not needed when I use a Structure.

Can anyone explain?

Thanks, Bob
On Sun, 20 Feb 2005 17:24:15 -0500, eBob.com
<eB******@totallyfakeisp.com> wrote:
I am trying to change some Structures to Classes. The Classes now
look like this ...

Public Class OneAttr
Public AttrName As String
Public Column As String
Public Caption As String
End Class

Public Class OneTable
Public ObjectName As String
Public TableName As String
Public NextIndex As Integer = -1
Public Attrs() As OneAttr
End Class

Public Class Product
Public ProdCode As String
Public NextTableIndex As Integer = -1
Public AtTables() As OneTable
End Class

I made the change, by the way, because I could not do the
initialization of the two fields you see initialized above when I was
using Structures.

But now I get an "object reference not set to an instance of an
object" Many, many hits in Google (this seems to be .Net's favorite
error message) but none were helpful.

Here's the code ...

Dim ThisProd As New Product
ThisProd.NextTableIndex = -1
...

If line.IndexOf("*OBJECT: ") = 0 Then
ThisProd.NextTableIndex = _
ThisProd.NextTableIndex + 1
TI = ThisProd.NextTableIndex 'shorthand
InTable = True
ReDim Preserve ThisProd.AtTables(TI)
ThisProd.AtTables(TI).NextIndex = -1 '< Error
ThisProd.AtTables(TI).ObjectName = _
line.Substring(9).Trim(" "c)

The error occurs on the statement which reads:
ThisProd.AtTables(TI).NextIndex = -1

This code worked when I was using Structures. TI is 0, so I think
that I have created the 1st element of ThisProd.AtTables().

I'll appreciate any and all help, pointers, or sympathy.

Thanks, Bob


Nov 21 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.