deserialized list in singleton grows and grows

M

Monty

Hello, I have a singleton settings class (.Net 2.0 framework) that I
serialize/deserialize to XML. On my settings class is a shared list of
integers. If I have two numbers in my list and I deserialize my class
successive times, the count of integers in my list grows by 2 each time when
I would expect it to remain at 2. When I run this code (below) and click the
button multiple times, my immediate window shows the following results:

2
4
6
8
10

Can anyone tell me what's going on here? TIA.

Imports System.Xml.Serialization
<Serializable()> _
Public Class cMySettings
Public Shared UserIDs As List(Of Integer)
Public Property zUserIDs() As List(Of Integer)
Get
Return UserIDs
End Get
Set(ByVal value As List(Of Integer))
UserIDs = value
End Set
End Property
End Class

Public Class Form1
Private Const sXML As String = _
"<?xml version=""1.0"" encoding=""utf-16""?> <cMySettings> " & _
"<zUserIDs><int>1</int><int>2</int></zUserIDs></cMySettings>"

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim myStream As New System.IO.StringReader(sXML)
Dim serializer As New
System.Xml.Serialization.XmlSerializer(GetType(cMySettings))
serializer.Deserialize(myStream)
Debug.Print(cMySettings.UserIDs.Count)
End Sub
End Class
 
R

rowe_newsgroups

Hello, I have a singleton settings class (.Net 2.0 framework) that I
serialize/deserialize to XML. On my settings class is a shared list of
integers. If I have two numbers in my list and I deserialize my class
successive times, the count of integers in my list grows by 2 each time when
I would expect it to remain at 2. When I run this code (below) and click the
button multiple times, my immediate window shows the following results:

2
4
6
8
10

Can anyone tell me what's going on here? TIA.

Imports System.Xml.Serialization
<Serializable()> _
Public Class cMySettings
Public Shared UserIDs As List(Of Integer)
Public Property zUserIDs() As List(Of Integer)
Get
Return UserIDs
End Get
Set(ByVal value As List(Of Integer))
UserIDs = value
End Set
End Property
End Class

Public Class Form1
Private Const sXML As String = _
"<?xml version=""1.0"" encoding=""utf-16""?> <cMySettings> " & _
"<zUserIDs><int>1</int><int>2</int></zUserIDs></cMySettings>"

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim myStream As New System.IO.StringReader(sXML)
Dim serializer As New
System.Xml.Serialization.XmlSerializer(GetType(cMySettings))
serializer.Deserialize(myStream)
Debug.Print(cMySettings.UserIDs.Count)
End Sub
End Class

Quick guess here - I didn't run your code.

You have UserIds as a shared field, so every instance you create is
going to adds those ids to the shared field. And since the shared
field won't "die" until the program does, you will continue to get
higher and higher number of UserIds. You should either pull the shared
specifier (if they don't need shared across instances) or implement
IDisposable and clean up the shared property when the instance dies.
Remember however that for the IDisposable strategy to work, you'll
need to explicitly call Dispose since it's a crapshoot at best trying
to let the GC does this for you (you'll never know when the objects
are removed). You best best (imo) is to just pull the shared specifier
if at all possible.

Thanks,

Seth Rowe [MVP]
 
P

pamela fluente

Quick guess here - I didn't run your code.

You have UserIds as a shared field, so every instance you create is
going to adds those ids to the shared field. And since the shared
field won't "die" until the program does, you will continue to get
higher and higher number of UserIds. You should either pull the shared
specifier (if they don't need shared across instances) or implement
IDisposable and clean up the shared property when the instance dies.
Remember however that for the IDisposable strategy to work, you'll
need to explicitly call Dispose since it's a crapshoot at best trying
to let the GC does this for you (you'll never know when the objects
are removed). You best best (imo) is to just pull the shared specifier
if at all possible.

Thanks,

Seth Rowe [MVP]- Nascondi testo tra virgolette -

- Mostra testo tra virgolette -

probably, if you need the shared, you could perhaps:


<Serializable()> Public Class cMySettings

Sub New()
UserIDs.Clear()
End Sub

Public Shared UserIDs As New List(Of Integer)

Public Property zUserIDs() As List(Of Integer)
Get
Return UserIDs
End Get
Set(ByVal value As List(Of Integer))
UserIDs = value
End Set
End Property

End Class



-P
 
M

Monty

Thanks Seth, but I guess I don't understand why it would ~add~ to the list
rather than ~replace~ it each time I deserialize my settings? For instance,
if I add a "Name" string property to my singleton (full code below) and
output the name each time along with the count, I get this:

2
Bubba
4
Bubba
6
Bubba
8
Bubba

But given the way the list behaves, why wouldn't I get this?

2
Bubba
4
BubbaBubba
6
BubbaBubbaBubba
8
BubbaBubbaBubbaBubba


[Updated code:]

Imports System.Xml.Serialization
<Serializable()> _
Public Class cMySettings
Public Shared UserIDs As List(Of Integer)
Public Shared Name As String
Public Property zName() As String
Get
Return Name
End Get
Set(ByVal value As String)
Name = value
End Set
End Property
Public Property zUserIDs() As List(Of Integer)
Get
Return UserIDs
End Get
Set(ByVal value As List(Of Integer))
UserIDs = value
End Set
End Property
End Class
Public Class cMyEmp
Private _Name As String
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
End Class
Public Class Form1
Private Const sXML As String = _
"<?xml version=""1.0"" encoding=""utf-16""?> <cMySettings> " & _
"<zUserIDs><int>1</int><int>2</int></zUserIDs>" & _
"<zName>Bubba</zName>" & _
"</cMySettings>"

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim myStream As New System.IO.StringReader(sXML)
Dim serializer As New XmlSerializer(GetType(cMySettings))
serializer.Deserialize(myStream)
Debug.Print(cMySettings.UserIDs.Count)
Debug.Print(cMySettings.Name)
End Sub
End Class
 
R

rowe_newsgroups

probably, if you need the shared, you could perhaps:

<Serializable()> Public Class cMySettings

Sub New()
UserIDs.Clear()
End Sub

Public Shared UserIDs As New List(Of Integer)

Public Property zUserIDs() As List(Of Integer)
Get
Return UserIDs
End Get
Set(ByVal value As List(Of Integer))
UserIDs = value
End Set
End Property

End Class

-P

One nasty side effect of this is that if you create back to back
cMySettings classes, both will show the most recent items, losing
whatever was added by the first instance. You mention "singleton" in
your subject so hopefully you just haven't added in the singleton
pattern yet so once you do that it should take care of the problem.
Though if you implement singleton, I don't see a reason for the shared
variable.....

Thanks,

Seth Rowe [MVP]
 

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