Creating a list of a class

  • Thread starter Thread starter Dale Atkin
  • Start date Start date
D

Dale Atkin

Still trying to come to grips with all the new features .NET gives me
(migrating from VB6), and I'm feeling like a real newbie here. I'm sure
there is an easy way to do this, but for some reason the 'obvious' solution
isn't working.

What I want to do, is create a list of a particular class, one for each of
the contents in a directory.

The code I'm using is as follows:

Private Sub LoadLocalFeatures(ByRef localFeatures As List(Of
clsFeature))
Dim ftrPath As New
IO.DirectoryInfo(IO.Path.Combine(GetApplicationDataDirectory, "ftrs\"))
Dim ftrFiles() As IO.FileInfo
Dim ftr As clsFeature
ftrFiles = ftrPath.GetFiles("FTR*.xml")
For i = 0 To UBound(ftrFiles)
ftr = New clsFeature
ftr.file = ftrFiles(i)
LoadFeature(ftr)
localFeatures.Add(ftr)
Next
End Sub

Now, I would have thought that by declaring ftr = New clsFeature, that it
would create a new instance of the feature class, that would be
manipulatable seperately from the old instance. The problem is, as soon as I
try to change the new instance, the old one updates as well. (as soon as I
hit the line ftr.file = ftrFiles(i), all of the members of the list get
updated with the new value)

For the life of me, I can't figure out another way to tackle this problem. I
need an indeteriminate number of clsFeature objects, added to a list. The
weirdest thing is, I was sure this code was working this morning??

Any bright ideas?

Dale

Here is the property Let on file, just in case you see something weird in
there:

<XmlIgnore()> Private Shared _file As FileInfo
<XmlIgnore()> Public Property file() As FileInfo
Get
Return _file
End Get
Set(ByVal value As FileInfo)
_file = value
id = file.Name
End Set
End Property
 
Still trying to come to grips with all the new features .NET gives me
(migrating from VB6), and I'm feeling like a real newbie here. I'm sure
there is an easy way to do this, but for some reason the 'obvious' solution
isn't working.

What I want to do, is create a list of a particular class, one for each of
the contents in a directory.

The code I'm using is as follows:

Private Sub LoadLocalFeatures(ByRef localFeatures As List(Of
clsFeature))
Dim ftrPath As New
IO.DirectoryInfo(IO.Path.Combine(GetApplicationDataDirectory, "ftrs\"))
Dim ftrFiles() As IO.FileInfo
Dim ftr As clsFeature
ftrFiles = ftrPath.GetFiles("FTR*.xml")
For i = 0 To UBound(ftrFiles)
ftr = New clsFeature
ftr.file = ftrFiles(i)
LoadFeature(ftr)
localFeatures.Add(ftr)
Next
End Sub

Now, I would have thought that by declaring ftr = New clsFeature, that it
would create a new instance of the feature class, that would be
manipulatable seperately from the old instance. The problem is, as soon as I
try to change the new instance, the old one updates as well. (as soon as I
hit the line ftr.file = ftrFiles(i), all of the members of the list get
updated with the new value)

For the life of me, I can't figure out another way to tackle this problem. I
need an indeteriminate number of clsFeature objects, added to a list. The
weirdest thing is, I was sure this code was working this morning??

Any bright ideas?

Dale

Here is the property Let on file, just in case you see something weird in
there:

<XmlIgnore()> Private Shared _file As FileInfo
<XmlIgnore()> Public Property file() As FileInfo
Get
Return _file
End Get
Set(ByVal value As FileInfo)
_file = value
id = file.Name
End Set
End Property

Based on the code you posted, it should work as you expect it to. The
only thing I can think that might affect it is the call to LoadFeature
inside the loop. Since you haven't provided the code for that, I
can't say whether or not that might be causing a problem.

Can you post a short but complete code sample that duplicates the
problem?

Chris
 
Still trying to come to grips with all the new features .NET gives me
(migrating from VB6), and I'm feeling like a real newbie here. I'm sure
there is an easy way to do this, but for some reason the 'obvious' solution
isn't working.

What I want to do, is create a list of a particular class, one for each of
the contents in a directory.

The code I'm using is as follows:

Private Sub LoadLocalFeatures(ByRef localFeatures As List(Of
clsFeature))
Dim ftrPath As New
IO.DirectoryInfo(IO.Path.Combine(GetApplicationDataDirectory, "ftrs\"))
Dim ftrFiles() As IO.FileInfo
Dim ftr As clsFeature
ftrFiles = ftrPath.GetFiles("FTR*.xml")
For i = 0 To UBound(ftrFiles)
ftr = New clsFeature
ftr.file = ftrFiles(i)
LoadFeature(ftr)
localFeatures.Add(ftr)
Next
End Sub

Now, I would have thought that by declaring ftr = New clsFeature, that it
would create a new instance of the feature class, that would be
manipulatable seperately from the old instance. The problem is, as soon as I
try to change the new instance, the old one updates as well. (as soon as I
hit the line ftr.file = ftrFiles(i), all of the members of the list get
updated with the new value)

For the life of me, I can't figure out another way to tackle this problem. I
need an indeteriminate number of clsFeature objects, added to a list. The
weirdest thing is, I was sure this code was working this morning??

Any bright ideas?

Dale

Here is the property Let on file, just in case you see something weird in
there:

<XmlIgnore()> Private Shared _file As FileInfo
<XmlIgnore()> Public Property file() As FileInfo
Get
Return _file
End Get
Set(ByVal value As FileInfo)
_file = value
id = file.Name
End Set
End Property

I assume the property file() is part of clsFeature. The problem is
that you have declared the private backing field for file() as Shared.
That means all instances of clsFeature share the same private backing
field. You do have one instance of clsFeature for each item in the
list, but they all share the same value for file().

Some more comments on your code.

There is no reason to declare the parameter to LoadLocaFeatures as
ByRef. You only need ByRef if the routine changes the parameter
itself, such as:

localFeatures = New List(Of clsFeature)

You are only modifying the object, not changing the object.

I would normally declare variables that are only used inside a loop,
such as ftr, inside the loop. That makes it clearer that the variable
is used only inside the loop:

ftrFiles = ftrPath.GetFiles("FTR*.xml")
For i As Integer = 0 To UBound(ftrFiles)
Dim ftr As New clsFeature

If you always pass in an empty list, I would change the method to be a
Function and have it return a list.
 
I assume the property file() is part of clsFeature. The problem is
that you have declared the private backing field for file() as Shared.
That means all instances of clsFeature share the same private backing
field. You do have one instance of clsFeature for each item in the
list, but they all share the same value for file().

Ahhhhh.... I'd misunderstood the meaning of the shared keyword. I'd assumed
it was something to do with access rights on the variable. I forget why I
put that in there, but I guess this underscores the need to understand
absolutely everything about any sample code you look at.
Some more comments on your code.

There is no reason to declare the parameter to LoadLocaFeatures as
ByRef. You only need ByRef if the routine changes the parameter
itself, such as:

localFeatures = New List(Of clsFeature)

You are only modifying the object, not changing the object.

Thanks, I recognize that (at least now I do....I was digging in to help
files last night and figured this out). I changed it to 'ByRef', just in
case I'd been misunderstanding something, and forgot to change it back
before I posted the code.
I would normally declare variables that are only used inside a loop,
such as ftr, inside the loop. That makes it clearer that the variable
is used only inside the loop:

ftrFiles = ftrPath.GetFiles("FTR*.xml")
For i As Integer = 0 To UBound(ftrFiles)
Dim ftr As New clsFeature


Old habits die hard ;) (although I agree that this is probably a bit
'cleaner' given VB's support for variables that are only available in a
given block).
If you always pass in an empty list, I would change the method to be a
Function and have it return a list.

You know, I'm not sure why I did it as a sub. A Function probably would have
been more appropriate.

Dale
 
Back
Top