Question Accessing Properties of Derived Objects Within List

LeoNim

New member
Joined
Sep 8, 2016
Messages
1
Programming Experience
Beginner
Hello! As the title mentioned, I have a question regarding lists of objects, including derived classes. If it helps, a bit of background information on myself regarding programming experience: I self-taught a bit of Visual Basic and C++ back when I was in high school, but I don't have any official training or expertise with programming. I'm self-teaching C#, and I believe that I have a fairly solid grasp on at least the basic fundamentals, though obviously I still have quite a ways to go. I'm currently using Visual Studio Express 2015 for Desktop, which I believe uses the latest .NET framework, though I'm not 100%.

For a project I've wanted to do since the days I tried self-teaching C++, and to practice the fundamentals of OOP, classes and inheritance, I'm working on a basic RPG style game, or at least the core mechanics of one. Right now, I'm working on code for items. Without just slapping the entire code onto the post, I have the following inheritance structure so far:

Items - Base class, is abstracted;
Equipment : Items;
Consumables : Items; - Still in progress, but a couple types of objects will derive from Consumables with different properties;
Armor : Equipment;
Weapon : Equipment

I've also created a Character class, which, among other things, has a System.Collections.Generic.List<Items> called inventory. The intended application of this is as you'd expect; I want the character to have an inventory of items, naturally. Because the List is of Items, I can happily shove any derived class item into it, and the program has no issue with this whatsoever. My Main method runs through a test where it initializes a character, provides an inventory, creates instances of several items, and adds them to the List. This works 100%! I'm happy with the results so far.

However, the issue I'm running into is if I want to access the Properties of a derived class within that inventory! Reading and writing properties that are present in Items isn't a problem; properties such as Name, Weight, ItemValue, and whatnot, I can get and set to my heart's content without any trouble. However, let's say I wanted to grab the ArmorClass of an armor piece, or change it... that particular Property is all the way down in Armor, two levels of inheritance lower than Items. If I try to access it, the compiler complains that Items doesn't have that property. I don't want to move the property to Items, since a number of Items won't need such a property.

Having looked around online, I did manage to find a way to get info, though it's rather clunky and potentially resource heavy. In this case, the aim of the code is to *equip* an item by toggling the boolean Equipped in the Equipment derived class.

C#:
Type type = inventory[invPos].GetType(); // Make sure the item to be equipped is fetched from inventory and is actually armor.
Type compare = typeof(Armor); // A point of comparison; type should equal this if the item specified is actually an armor piece.
if (type != compare)
    return 3; // Temp debugging error code.

Armor a = (Armor)inventory[invPos]; // Brings in copy of item to inspect - there's got to be a better way.

As I mentioned in the comments, for getting properties that belong to derived classes, this does work as intended, but bringing in a copy of an entire object to inspect one property seems needlessly frivolous with system resources. It looks like a hack to me, frankly. Granted, I'm relatively new at programming, but it just feels like there should be a more elegant solution - I've noticed c# tends to be simpler and easier than C++ in a few ways, so it'd be odd to me that this isn't one of them.

As for setting properties, again with the code that I'm not terribly fond of. Skipping past some validity checking, this is the code that actually flips the switch:

C#:
// Now that we've verified that the item is equippable and no obstructing items are in the way, equip it.
a.Equipped = true;

// Dirty trick - removing the non-equipped version and replacing it with our copy.
inventory.RemoveAt(invPos);
inventory.Insert(invPos, a);
return 0; // Success.

Again, this does technically work, but it just seems so indirect and wrong. I feel like I should be able to access the Methods of an instance of Armor even if it's in a list of Items, and modify without having to make a copy, modify the copy, delete the original and shove my new copy in its place. The problem is, I'm likely not as familiar with the large array of keywords c# puts at my disposal as the users of this board are. If you would, please, help me clean up my code; I highly appreciate any assistance I can get.

EDIT: I've been looking up more resources as able, while I await a reply. I've managed to find a better way to accomplish what I was doing in the first snippet: The "as" keyword, which I wasn't aware of before. So now it looks like this:

C#:
/* Pre Equip Check: Make sure the item to be equipped is fetched from inventory and is actually armor.
 * If the item is not armor, return error 3.*/

Armor a = inventory[invPos] as Armor;
if (a == null)
    return 3;

And that works, much more cleanly, than what I had before. I tested it by equipping an armor, then trying to use the EquipArmor method to equip a weapon as one - it didn't work, as expected.

So I guess now the biggest thing I'm still stuck on is the second part. I really don't like making a copy of an object, modifying the copy, deleting the original and inserting the new one in its place. For something like this, it's probably not the end of the world, but I'm picturing some massive object with huge numbers of fields and properties, and thinking to myself that this isn't the best practice. Is there a cleaner way to accomplish what I'm doing there?
 
Last edited:
Back
Top Bottom