Home All Groups Group Topic Archive Search About

Creating a list of a class

Author
8 Jun 2009 6:38 PM
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

Author
8 Jun 2009 9:11 PM
dunawayc
Show quote Hide quote
On Jun 8, 1:38 pm, "Dale Atkin" <labrad***@ibycus.com> wrote:
> 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
Author
9 Jun 2009 6:09 AM
Jack Jackson
Show quote Hide quote
On Mon, 8 Jun 2009 12:38:41 -0600, "Dale Atkin" <labrad***@ibycus.com>
wrote:

>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.
Author
9 Jun 2009 4:10 PM
Dale Atkin
>
> 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