Using Classes as List Items

Z

zacks

I have written a serialized class that has several properties that are
typed as a list of type class. When I deserialize an XML file, the list
is populated just fine. But I am having trouble manually loading the
class for serialization when the class has not been initialized by a
deserialize. If I add three instances of a class to the list, each with
different values for their properties, the XML file created by
serialization has three items for that property, but the values in all
three are the same values, the values of the last class added to the
list. I have tried a test of this that merely loads up a list of
classes in a class that is not being serialized and dump the property
values with the same result. Any ideas?

Sample code:

My custom class to be listed:

Public Class clsItem

Private _Part1 As String
Private _Part2 As String

Public Property Part1() As String
Get
Return _Part1
End Get
Set(ByVal value As String)
_part2 = value
End Set
End Property

Public Property Part2() As String
Get
Return _Part2
End Get
Set(ByVal value As String)
_Part2 = value
End Set
End Property

End Class

Code to load up the list and dump it:

Dim myItem As New clsItem
Dim myItems As New List(Of clsItem)
Dim i As Integer = 1

myItem.Part1 = "This is Part 1 the First Item in the List"
myItem.Part2 = "This is Part 2 the First Item in the List"
myItems.Add(myItem)
myItem.Part1 = "This is Part 1 the Second Item in the List"
myItem.Part2 = "This is Part 2 the Second Item in the List"
myItems.Add(myItem)
myItem.Part1 = "This is Part 1 the Third Item in the List"
myItem.Part2 = "This is Part 2 the Third Item in the List"
myItems.Add(myItem)
For Each myItem In myItems
Debug.WriteLine("Item Number " & CStr(i))
Debug.WriteLine("Part1 = " & myItem.Part1)
Debug.WriteLine("Part2 = " & myItem.Part2)
i += 1
Next

The output:

Item Number 1
Part1 =
Part2 = This is Part 2 the Third Item in the List
Item Number 2
Part1 =
Part2 = This is Part 2 the Third Item in the List
Item Number 3
Part1 =
Part2 = This is Part 2 the Third Item in the List

Notice that the first property called Part1 never gets any value.
 
L

Larry Lard

I have written a serialized class that has several properties that are
typed as a list of type class. When I deserialize an XML file, the list
is populated just fine. But I am having trouble manually loading the
class for serialization when the class has not been initialized by a
deserialize. If I add three instances of a class to the list, each with
different values for their properties [snip]

Dim myItem As New clsItem
Dim myItems As New List(Of clsItem)
Dim i As Integer = 1

myItem.Part1 = "This is Part 1 the First Item in the List"
myItem.Part2 = "This is Part 2 the First Item in the List"
myItems.Add(myItem)
myItem.Part1 = "This is Part 1 the Second Item in the List"
myItem.Part2 = "This is Part 2 the Second Item in the List"
myItems.Add(myItem)
myItem.Part1 = "This is Part 1 the Third Item in the List"
myItem.Part2 = "This is Part 2 the Third Item in the List"
myItems.Add(myItem)

I only see one instance. You want a myItem to be a New clsItem each
time, before you set its properties and add it to the list.
 
J

Jay B. Harlow [MVP - Outlook]

Zacks,
As Larry suggests, you only have a single instance of clsItem.

I would define a constructor on clsItem, something like:

Public Sub New(part1 As String, part2 As String)
_part1 = part1
_part2 = part2
End Sub

Then the code to create the list can be reduced to:

Dim myItem As clsItem

myItem = New clsItem("This is Part 1 the First Item in the List",
"This is Part 2 the First Item in the List")
myItems.Add(myItem)
myItem = New clsItem("This is Part 1 the Second Item in the List",
"This is Part 2 the Second Item in the List")
myItems.Add(myItem)
myItem = New clsItem("This is Part 1 the Third Item in the List",
"This is Part 2 the Third Item in the List")
myItems.Add(myItem)


Or even:

myItems.Add(New clsItem("This is Part 1 the First Item in the List",
"This is Part 2 the First Item in the List"))
myItems.Add(New clsItem("This is Part 1 the Second Item in the
List", "This is Part 2 the Second Item in the List"))
myItems.Add(New clsItem("This is Part 1 the Third Item in the List",
"This is Part 2 the Third Item in the List"))
For Each myItem As clsItem In myItems


I would also consider creating a clsItemCollection that inherits from
System.Collections.ObjectModel.Collection(Of T), allowing a parameterized
Add statement

Public Class clsItemCollection
Inherits System.Collections.ObjectModel.Collection(Of clsItem)

Public Overloads Sub Add(ByVal part1 As String, ByVal part2 As
String)
Add(New clsItem(part1, part2))
End Sub

End Class

Giving:

Dim myItems As New clsItemCollection

myItems.Add("This is Part 1 the First Item in the List", "This is
Part 2 the First Item in the List")
myItems.Add("This is Part 1 the Second Item in the List", "This is
Part 2 the Second Item in the List")
myItems.Add("This is Part 1 the Third Item in the List", "This is
Part 2 the Third Item in the List")

Which limits (encapsulates) the multiple calls to the constructor to the
overload Add method, note clsItemCollection also has an Add(clsItem) method.

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


|I have written a serialized class that has several properties that are
| typed as a list of type class. When I deserialize an XML file, the list
| is populated just fine. But I am having trouble manually loading the
| class for serialization when the class has not been initialized by a
| deserialize. If I add three instances of a class to the list, each with
| different values for their properties, the XML file created by
| serialization has three items for that property, but the values in all
| three are the same values, the values of the last class added to the
| list. I have tried a test of this that merely loads up a list of
| classes in a class that is not being serialized and dump the property
| values with the same result. Any ideas?
|
| Sample code:
|
| My custom class to be listed:
|
| Public Class clsItem
|
| Private _Part1 As String
| Private _Part2 As String
|
| Public Property Part1() As String
| Get
| Return _Part1
| End Get
| Set(ByVal value As String)
| _part2 = value
| End Set
| End Property
|
| Public Property Part2() As String
| Get
| Return _Part2
| End Get
| Set(ByVal value As String)
| _Part2 = value
| End Set
| End Property
|
| End Class
|
| Code to load up the list and dump it:
|
| Dim myItem As New clsItem
| Dim myItems As New List(Of clsItem)
| Dim i As Integer = 1
|
| myItem.Part1 = "This is Part 1 the First Item in the List"
| myItem.Part2 = "This is Part 2 the First Item in the List"
| myItems.Add(myItem)
| myItem.Part1 = "This is Part 1 the Second Item in the List"
| myItem.Part2 = "This is Part 2 the Second Item in the List"
| myItems.Add(myItem)
| myItem.Part1 = "This is Part 1 the Third Item in the List"
| myItem.Part2 = "This is Part 2 the Third Item in the List"
| myItems.Add(myItem)
| For Each myItem In myItems
| Debug.WriteLine("Item Number " & CStr(i))
| Debug.WriteLine("Part1 = " & myItem.Part1)
| Debug.WriteLine("Part2 = " & myItem.Part2)
| i += 1
| Next
|
| The output:
|
| Item Number 1
| Part1 =
| Part2 = This is Part 2 the Third Item in the List
| Item Number 2
| Part1 =
| Part2 = This is Part 2 the Third Item in the List
| Item Number 3
| Part1 =
| Part2 = This is Part 2 the Third Item in the List
|
| Notice that the first property called Part1 never gets any value.
|
 
C

Cor Ligthert [MVP]

Zack,

I am curious, why are you building your own most simple small version of the
inbuilt great class the DataTable? I can assure you that they did think
about that one by Microsoft it seems for me that it has endless
possibilities..

Cor
 
J

Jay B. Harlow [MVP - Outlook]

Zacks,
BTW: I just noticed this in your code...

Debug.WriteLine is overloaded with a Category, you can "simplify" this:

| Debug.WriteLine("Item Number " & CStr(i))
| Debug.WriteLine("Part1 = " & myItem.Part1)
| Debug.WriteLine("Part2 = " & myItem.Part2)

to:

Debug.WriteLine(i, "Item Number")
Debug.WriteLine(myItem.Part1, "Part1")
Debug.WriteLine(myItem.Part2, "Part2")


--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


|I have written a serialized class that has several properties that are
| typed as a list of type class. When I deserialize an XML file, the list
| is populated just fine. But I am having trouble manually loading the
| class for serialization when the class has not been initialized by a
| deserialize. If I add three instances of a class to the list, each with
| different values for their properties, the XML file created by
| serialization has three items for that property, but the values in all
| three are the same values, the values of the last class added to the
| list. I have tried a test of this that merely loads up a list of
| classes in a class that is not being serialized and dump the property
| values with the same result. Any ideas?
|
| Sample code:
|
| My custom class to be listed:
|
| Public Class clsItem
|
| Private _Part1 As String
| Private _Part2 As String
|
| Public Property Part1() As String
| Get
| Return _Part1
| End Get
| Set(ByVal value As String)
| _part2 = value
| End Set
| End Property
|
| Public Property Part2() As String
| Get
| Return _Part2
| End Get
| Set(ByVal value As String)
| _Part2 = value
| End Set
| End Property
|
| End Class
|
| Code to load up the list and dump it:
|
| Dim myItem As New clsItem
| Dim myItems As New List(Of clsItem)
| Dim i As Integer = 1
|
| myItem.Part1 = "This is Part 1 the First Item in the List"
| myItem.Part2 = "This is Part 2 the First Item in the List"
| myItems.Add(myItem)
| myItem.Part1 = "This is Part 1 the Second Item in the List"
| myItem.Part2 = "This is Part 2 the Second Item in the List"
| myItems.Add(myItem)
| myItem.Part1 = "This is Part 1 the Third Item in the List"
| myItem.Part2 = "This is Part 2 the Third Item in the List"
| myItems.Add(myItem)
| For Each myItem In myItems
| Debug.WriteLine("Item Number " & CStr(i))
| Debug.WriteLine("Part1 = " & myItem.Part1)
| Debug.WriteLine("Part2 = " & myItem.Part2)
| i += 1
| Next
|
| The output:
|
| Item Number 1
| Part1 =
| Part2 = This is Part 2 the Third Item in the List
| Item Number 2
| Part1 =
| Part2 = This is Part 2 the Third Item in the List
| Item Number 3
| Part1 =
| Part2 = This is Part 2 the Third Item in the List
|
| Notice that the first property called Part1 never gets any value.
|
 
G

Guest

Jay,

Is there a reason why, in the constructor, you assign the parameter values
directly to the private data elements instead of going through the property's
accessor method?

I know that in this particular example the class does not enforce any
business rules in the Set procedures. But I like the habit of always going
through the Set procedures. For example:

Public Sub New(part1 As String, part2 As String)
Me.Part1 = part1
Me.Part2 = part2
End Sub

That way I don't accidentally bypass code that might be added later in the
Set procedures.

What criteria do you use to decide how to assign values from the constructor
to the data elements of the class?

Kerry Moorman
 
J

Jay B. Harlow [MVP - Outlook]

| Is there a reason why, in the constructor, you assign the parameter values
| directly to the private data elements instead of going through the
property's
| accessor method?
Its the convention I've pretty much always used.

| ... But I like the habit of always going
| through the Set procedures. ...
Its a good habit to have, it really depends on the project/solution if I use
the fields directly or use the properties, as some projects/solutions don't
really call for special validation logic in the set methods...

| What criteria do you use to decide how to assign values from the
constructor
| to the data elements of the class?
If the property set routines include special validation logic. Of course if
special validation logic is added as an after thought, then its possible the
constructor will be missed. One would hope Unit Testing would catch these
cases ;-)

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Jay,
|
| Is there a reason why, in the constructor, you assign the parameter values
| directly to the private data elements instead of going through the
property's
| accessor method?
|
| I know that in this particular example the class does not enforce any
| business rules in the Set procedures. But I like the habit of always going
| through the Set procedures. For example:
|
| Public Sub New(part1 As String, part2 As String)
| Me.Part1 = part1
| Me.Part2 = part2
| End Sub
|
| That way I don't accidentally bypass code that might be added later in the
| Set procedures.
|
| What criteria do you use to decide how to assign values from the
constructor
| to the data elements of the class?
|
| Kerry Moorman
|
|
| "Jay B. Harlow [MVP - Outlook]" wrote:
|
| > I would define a constructor on clsItem, something like:
| >
| > Public Sub New(part1 As String, part2 As String)
| > _part1 = part1
| > _part2 = part2
| > End Sub
| >
|
 
E

Enfor

I think your Part1 Set Property has a typo it should be writting to _Part1
not _Part2
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top