Can a class maintain a shared collection of its own instances

Hi,

Can a class (say Person) maintain a shared collection of instances of all Person objects created (maybe an array called Persons).

i.e. Whenever a Person instance is created, it adds itself to the Persons collection which is a shared member and accessible to all of the created person instances?

I wonder if you could do it as part of the constructor, but the instance doesnt exist at that point....

Hope this makes sense.

p_love
LVL 1
p_loveAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

p_loveAuthor Commented:
What I mean is is this feasible, or how can it be created:

Class Person
    Shared Persons as New Collection

    Sub New()
        ....initialise here
        Persons.Add Me
    End Sub

End Class

or there abouts
0
PockyMasterCommented:
There are a couple of ways to do it for you.

Create a person factory e.g. and let that class create the person for you (and copy an instance to the persons class while doing it, with the new person added to it already)

or make the persons class a singleton.
and just add an instance to it while creating your person (actually i like the first solution better)

0
Mike TomlinsonMiddle School Assistant TeacherCommented:
You've answered your own question p_love!...that's exactly how to do it.

Try this out to prove to yourself that each instance is beind added to the ArrayList

Public Class Form1
    Inherits System.Windows.Forms.Form

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim p As New Person("Person" & Person.Persons.Count + 1)
        Dim i As Integer
        Debug.WriteLine("Person Instances: " & Person.Persons.Count)
        For i = 0 To Person.Persons.Count - 1
            Debug.WriteLine(i & ": " & Person.Persons(i).Name)
        Next
    End Sub


    Public Class Person
        Public Shared Persons As New ArrayList

        Public Name As String

        Public Sub New(ByVal Name As String)
            Me.Name = Name
            Person.Persons.Add(Me)
        End Sub

    End Class

End Class
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

Bob LearnedCommented:
Although it may be feasible, I certainly wouldn't do it that way--it's so self referential.

Bob
0
PockyMasterCommented:

you might think about it like this:


Public Class CPersonFactory

    Private Shared _instance As CPersonFactory
    Private Shared _personList As CPersonList

    Public Function CreatePerson(ByVal sName As String) As CPerson
        Dim newPerson As New CPerson(sName, _personList)
        _personList.addPerson(newPerson)

        Return newPerson
    End Function

    Private Sub New()
        _personList = New CPersonList
    End Sub

    Public Shared Function GetInstance() As CPersonFactory
        If _instance Is Nothing Then
            _instance = New CPersonFactory
        End If

        Return _instance
    End Function
End Class


Public Class CPerson
    Private _sName As String
    Private _PersonList As CPersonList
    Public Sub New(ByVal sName As String, ByVal PersonList As CPersonList)
        _sName = sName
        _PersonList = PersonList
    End Sub

    Public ReadOnly Property Name() As String
        Get
            Return _sName
        End Get
    End Property

    Public ReadOnly Property PersonList() As CPerson()
        Get
            Return _PersonList.Persons
        End Get
    End Property
End Class

Public Class CPersonList
    Private _arPersons As ArrayList

    Public Sub New()
        _arPersons = New ArrayList
    End Sub

    Public Sub addPerson(ByVal person As CPerson)
        _arPersons.Add(person)
    End Sub
    Public ReadOnly Property Persons() As CPerson()
        Get
            If _arPersons.Count = 0 Then
                Return Nothing
            Else
                Return DirectCast(_arPersons.ToArray(GetType(CPerson)), CPerson())
            End If
        End Get
    End Property

End Class

and then call it like :
 Dim pf As CPersonFactory = CPersonFactory.GetInstance()
        Dim pers1 As CPerson = pf.CreatePerson("myPerson")
        Dim pers2 As CPerson = pf.CreatePerson("myOtherPerson")

'just an example to get your persons
        Dim allPersons() As CPerson = pers2.PersonList


Your factory in this case will make sure the personlist will stay alive
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Mike TomlinsonMiddle School Assistant TeacherCommented:
Bob and PockyMaster...

Can you two give a technical reason why the approach I posted is bad?  I have used that same construction in a flocking AI application where each instance of a class basically represents a "sheep" that moves based upon the collective "center of mass" of all the sheep in the flock.  Each sheep must have knowledge of the all the other sheep (instances of the same class) so that it can make a decision as to how it should move.  The app literally ran for hours on end without any of the sheep being garbaged collected and when the app was shut down it properly released its resources.
0
PockyMasterCommented:
You might try an observer pattern to that one.

http://www.dofactory.com/Patterns/PatternObserver.aspx

The pattern will take care of updating a lot of observers (all of your sheep ) in case one of your sheep changes

And about your question....
First of all.. there are many ways to solve a problem, but there are ways that a lot of people use, and therefor a lot of times considered the way to go.

But you might consider the following:
At the moment you're exposing a Persons collection in your Person class.
Since .NET decides the type of your collection based on the first element in your collection, it could contain whatever.
So to be a little more on the safe side, you might implement a AddPerson method.
You might see the confusion arising here... A AddPerson method on a Person class? Adding a person to a person?
Apart from pregnancy that's a weird way to go.
So from OO point of view, the implementation could be a little confusing in some cases, doesn't mean that it will not compile or run.

When I want to find a list of persons, I will not look for the object in a person, but will look at a higher level.
Ok, a person might hold a reference to it, but I think the list should be kept outside.
Actually, the shared mechanism keeps it seperated, but under the same classifier.
Which in my humble opinion is not a lucky choice.
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
Fair enough.  Thanx for the discussion...  =)
0
PockyMasterCommented:
P love, was this any good for you?
0
p_loveAuthor Commented:
Hi PockyMaster,

I like the Factory implementation.  I guess you are creating a Factory singleton, but isnt this introducing a lot of coupling.  Also, there is nothing stopping a person creating a Person instance and passing in any old CPersonList instance.  By having the collection associated with the Person class itself, and the constructor of the Person class explicitly being responsible for adding each created instance to its own collection, arent you simplifying the design, reducing coupling, and leaving the Person class responsible for itself?

Also could you explain:

  Return DirectCast(_arPersons.ToArray(GetType(CPerson)), CPerson())

Thanks everybody
0
PockyMasterCommented:
Well, it all comes down to taste and good/bad practises. I like the design patterns way to do it (which actually just is a collection of best practises).

Your version is simpler, but again my previous arguments will apply to that, think it's a matter of pro/cons.

The directCast I use to convert the internal arraylist to an Array of CPerson,
so I will introduce a little more type-safety here.

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.