LordYabo
LordYabo

Reputation: 11

Are there gotchas when copying a base class reference to child class? (downcasting)

I have List<Character> citizens. Citizens have various properties, most important are:

public string firstname;
public Dictionary<Character, Relationship> relationships { get; set; }
...

Citizens can become things after they are created, like a Trader : Character.
So in my list of citizens I want to replace a reference to a Character with one to a Trader.

I read and understand the answers about downcasting. So I will do the constructor approach:

public Trader(Character c)
{
    firstname = c.firstname;
    relationships = c.relationships;
    ...         
}

And then I want to replace the reference to the old Character and use this fancy new Trader:

citizens.Remove(old);
citizens.Add(fancyTrader);

What concerns me is references to the relationship dictionary, does that not just cause the old Character object to hang around forever, meaning there are two copies of this guy in memory and the old one will never be garbage collected away?

I'm concerned because I have tens of thousands of these citizens.

Upvotes: 0

Views: 58

Answers (2)

Bradley Uffner
Bradley Uffner

Reputation: 17001

One way to work around this is to use composition instead inheritance. Consider abstracting your Character information in to multiple parts. The Character class holds the name data and relationships, while a Role class holds their "job". Trader would be a subclass of Role, and Character would have a property on it for that citizen's role (or even a list of roles if they can have more than one.

This gives you a lot of flexibility, and also prevents your references from getting tangled up when a character changes roles.

Upvotes: 2

BradleyDotNET
BradleyDotNET

Reputation: 61379

Yes, you could have a memory leak in this scenario, but if you are at all careful about cleaning up after yourself you'll be fine (and this has nothing to do with downcasting).

The primary "gotchas" of downcasting are attempting it against a type that isn't actually what you are casting to, which is a runtime error (not ideal). With your approach, you need to make sure you understand that you are doing a shallow copy and the potential bugs that raises as well.

I would run the program for a while with a profiler, make sure you aren't having an ever-increasing number of references and use that to see if you have a problem. Having a "Dispose" method on your Citizen that cleans up the relationships dictionary when the object is no longer needed would go a long way towards solving any such issues.

Upvotes: 0

Related Questions