Jump to content
  • Advertisement
Sign in to follow this  
captain_crunch

Exchanging a referenced object for another

This topic is 3757 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I have a list collection that is referenced from many other objects. Now I want to exchange the list collection for a different one. The old one is deleted. The client objects should carry on as if nothing had happened. Is there a software pattern that will allow me to do this, and have all the referencing objects point to the new collection, or in effect work on the new collection from now on, without having to reset all the references one at a time? I code in C# but I would think this is a general issue...

Share this post


Link to post
Share on other sites
Advertisement
You have to use an additional level of indirection. Have all your objects reference an object that itself references the container. When you replace the container with another, change the single reference to that container, and all the other objects will use the new one.

Share this post


Link to post
Share on other sites
In this case I'm merging two lists. Only one list will be kept. If I use your approach and I have an in-between object for each list to start with, I will then end up with two in-between objects referencing the same list.
I suppose this is an acceptable solution...

Share this post


Link to post
Share on other sites
I think the solution you proposed is the right one. I will create an encapsulating class and use that instead of the list.

I have but one more question, if I may...

In the new encapsulating class, do you think it matters whether I:

Expose the list as a public member and perform operations on it directly

Or

Implement all used methods, including the indexing operator, and pass the calls through to the private list member?

Share this post


Link to post
Share on other sites
Ummm...
Why not do something like this.



void MergeLists(List<object> listA, List<object> listB)
{
listA.AddRange(listB);
listB = listA;
}




At the end, listA and listB should reference the same object. The old listB goes to the garbage collector and everyone referencing the list should still be happy.

Share this post


Link to post
Share on other sites
I'm pretty sure that wouldn't work. Setting the parameter to a new value doesn't affect the caller.

However, this might work:

void MergeLists(ref List<object> listA, ref List<object> listB)
{
listA.AddRange(listB);
listB = listA;
}


Using the ref keyword should make the change affect the caller. But it doesn't solve my problem, because I have many references to each list, and using this method will only affect the one caller, not the other references.

Share this post


Link to post
Share on other sites
You don't. Not really, at least, since you can't really "store" references to references in C# AFAIK.

You can try this:
class MyList
{
public List<object> List { get; set; }
}

class ClientA
{
public MyList Foo { get; set; }
// ...
}

class ClientB
{
public MyList Foo { get; set; }
// ...
}



// Initialisation somewhere
MyList foo;
foo.List = new List<object>();
ClientA clientA = new ClientA();
ClientB clientB = new ClientB();

clientA.Foo = foo;
clientB.Foo = foo;

// Somewhere else
foo.List = someOtherList;


Since all your clients hold a reference to the single MyList class, you can freely change the MyList.List member, and all your clients will then use the new list.

It's not an ideal solution, and there's probably a better way to do it. But it'd work.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sc4Freak
Since all your clients hold a reference to the single MyList class, you can freely change the MyList.List member, and all your clients will then use the new list.


Yeah, I thought I had made it, but the situation seems to be a bit more complicated. See, I want to merge the two lists. I have updated your example to show what I mean:


// Two containers
MyList fooA;
MyList fooB;
// Two lists
fooA.List = new List<object>();
fooB.List = new List<object>();
// Two clients, one for each container
ClientA clientA = new ClientA();
ClientB clientB = new ClientB();

clientA.Foo = fooA;
clientB.Foo = fooB;

// Somewhere else
// Merge the lists:
fooA.List = fooA.List.Append(fooB.List);
// set container B to point at the merged list:
fooB.List = fooA.List


Both containers now point to one list.
The problem comes when I need to merge the list again. To do this, I now have to change the List property on three containers, instead of two, to point to the same list. And the next time four, and so on. I would have to keep track of every container that has ever existed, forever, because I wouldn't know if any clients were still referencing it.

So I have replaced the problem of keeping track of the clients with keeping track of the new container objects.

Share this post


Link to post
Share on other sites
I'm not too good with C#, i mostly code in c++, but maybe this will work.

class TheList
{
list<Object> m_list;
list<Client> m_clients;

AddRefToClient(Client& c)
{
c.m_listRef = this;
m_clients.push_back(c);
}

//implement a remove reference from client

//1. overload a += operator or implement merge function that takes in a TheList object
//2. inside this function iterate through passed in objects m_clients
//3. update each client as you iterate to to point to this list
// using the AddRefToClient function
};

class Client
{
friend class TheList; //not sure if this is available in c#, i think c#
//uses the internal keyword instead

list<Object>& m_listRef; //not sure if & is needed in c#

//do not provide a way to set the m_listRef reference
//the only way to set this reference would by through the TheList class
//AddRefToClient function
};

The friend keyword may not work in c# but I think the internal keyword does something similar also its used differently. Essentially what it would do in c++ is let "TheList" class to access private variables in the client class without exposing them to the rest of the app.

In any case, if that doesn't work you can always make a setter function or property for the m_listRef variable. The only problem with doing this is that the m_listRef variable will be exposed to the rest of the app allowing it to be changed by classes other then TheList.

Share this post


Link to post
Share on other sites
Yeah, registering the clients in some way might work... but I think I want a looser coupling still...

My newest idea is to not let the clients hold a reference to the lists at all. Instead, they will have an ID and call into a single map/dictionary that maps ID numbers to list references. In this way, I can update the map when lists are merged or switched about by changing the value part to point to the new list for the ID keys that are affected.

The downside to this approach is that the map could keep growing indefinitely as lists are merged, and more and more entries must be added.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!