Lesson 10.1 – Creating collections of objects

Lesson Objectives

At the end of this lesson, you will know…

  • How to store groups of objects in one property or variable, and read them later.


How to handle groups of objects

You may have noticed that there are properties missing from some of our classes. When outlining the program, we mentioned that the player will be able to have items in their inventory. The player will have quests. Quests have items that need to be turned in, to complete them. Monsters have items that can be looted from them.

We have a Quest class, and an Item class, but we don’t have any place to store them in the Player or Monster classes. We also need a way to store more than one item, since a Player will probably have more than one item in their inventory and could have more than one quest.

We do this with lists, or collections.

But before we create these list properties, we’re going to need a place to store some additional information for the items and quests.

For example, with the items in the Player’s inventory, we need to store the quantity of each items they have. It’s similar to what we’ll need to do with the Quest class – store the quantity of each item that is needed to complete the quest.

For the player’s quests, we also need a place to record whether or not the player has completed the quest.

In the Monster class, we want a list of the items that can be “looted” from the monster. This is called the “loot table”. We need to store the item, the percentage of times it is “dropped”, and if the item is a default loot item – in case the random number generator says that none of the loot items were dropped.

There are different ways to do this, but I’m going to show you a way that uses some additional classes.

So, let’s create these new classes, then add them as “list” properties to the existing Player, Monster, and Quest classes.


NOTE: In the video, the Quest class is missing the RewardItem property from the last lesson (shown at 6:52). You should keep that property in your class.


Link to video on YouTube


Step 1: Start Visual Studio Express 2013 for Desktop, and open the solution.


Step 2: Create these four new classes by right-clicking on the Engine project and selecting “Add”, then “Class…”. The four classes to create are named:










NOTE: We use a new datatype for two of these classes – “bool”. This stands for “Boolean” and is used to store a value of “true” or “false”. For example, in the PlayerQuest class, the “IsCompleted” property will store a value of “false”, until the player finishes the quest. Then we’ll store “true” in it.


Step 3: Now that we have the new classes, we can create properties for them in the Player, Quest, and Monster classes.

Edit the Player class, by double-clicking on it in the Engine project.

Look at line two of the Player class. In order to use lists, one variable or property to hold a collection of objects that are the same class, we need to have this line included. This is where your program will find everything it needs, in order to work with collections.

Add these two properties to the Player class:

Now you have two new properties that can hold lists containing InventoryItem and PlayerQuest objects.

Then, in the constructor code, add these new lines:

These two lines set the value of the new properties to empty lists. If we didn’t do this, the value for those properties would be “null” – nothing. By setting them to an empty list, we can add items to them later, because you can add objects to an empty list, but you can’t add object to nothing (null).


Player.cs (complete, with changes)



Step 4: Edit the Quest class. Add this new property:

In the constructor, add this new line, so the QuestCompletionItems list will be ready to have objects added to it:


Quest.cs (complete, with changes)



Step 5: Edit the Monster class, by adding this property:

And add this to the constructor, so the new property isn’t “null”:

NOTE 1: We didn’t need to set the string, integer, and Boolean properties to a default value because those datatypes have a built-in default value. However, Lists are null (non-existent), until you set them to an empty list (a new List object, with no values in it yet).

NOTE 2: We didn’t create new parameters in the constructor to pass in values for these new properties. We could have, but we are going to populate them a little differently – a way that I think is a little easier for someone new to programming.


Monster.cs (complete, with changes)




Almost every program I’ve written has included some type of list of collection. In the real world, we usually work with several items (e.g., display all the deposits into, and payments from, a bank account).

We’ll show how to add to, and work with, the objects in these lists very soon.


Source code for this lesson

Source code on GitHub (new classes)

Source code on GitHub (updated classes)


Source code on Dropbox (new classes)

Source code on Dropbox (updated classes)



Next lesson: Lesson 11.1 – Using a static class

Previous lesson: Lesson 09.1 – Using your classes as datatypes

All lessons: Learn C# by Building a Simple RPG Index


67 thoughts on “Lesson 10.1 – Creating collections of objects

  1. Hello

    I’ve started reading your tutorial for a while already and there is only 1 thing i’d have to say with all theses classes appearing, folders are a great thing to organize the project lol.

    Thanks for this awesome tutorial. It have been much easyier to understand how those things work with the details your are giving to us.

    Peace and nice work!

    1. Hello (and thank you),

      Yes, organizing classes is extremely important. Some of the large programs I’ve worked on have over 100 projects, thousands of classes, and over a million lines of source code.

      1. Honestly i’ve been saying that mainly because i didn’t see you talking about it even though there is quite a few classes already.

        Well, i guess it’s a bit of my own fault for not exploring Visual Studio a bit more too lol.

        1. Because this is a small program, that was originally only going to be the code from the first 16 lessons, I didn’t create folders for the classes. For the WPF version, I created the folders that I would normally use.

  2. Hey, just got upto this part of the tutorial but now starting to get errors that I can’t seem to see the problem to. Things Like

    Error CS0051 Inconsistent accessibility: parameter type ‘Item’ is less accessible than method ‘InventoryItem.InventoryItem(Item, int)’ Engine

    and that’s for most of the new classes just made.

    1. Hi Dylan,

      Check your classes and properties, to ensure they have “public”. From that message, I’m guessing that your Item class says “class Item”, instead of “public class Item”.

      Please let me know if that does not fix the errors.

  3. Thanks for your great lessons.

    Could you tell me how I can get weapon MaximumDamage inside that loop?

    foreach (InventoryItem inventoryItem in _player.Inventory)
    if (inventoryItem.Details is Weapon)
    // Weapon MaximumDamage?

    1. You’re welcome.

      In the foreach loop, the datatype of the “inventoryItem” variable is declared as “InventoryItem”. So, it is treated as an InventoryItem object – which does not have MinimumDamage or MaximumDamage properties. However, for InventoryItems that are also Weapons, we can “cast” it to Weapon – which has those properties.

      You could do it one of these two ways:

      Weapon itemCastAsWeapon = inventoryItem as Weapon;
      int maximumDamage = itemCastAsWeapon.MaximumDamage;


      int maximumDamage = (inventoryItem as Weapon).MaximumDamage;

      Another way to cast objects is
      Weapon itemCastAsWeapon = (Weapon)inventoryItem;

      However, with that technique, if the cast fails (when the object is not also a Weapon object), you get an error. When you use “inventoryItem as Weapon”, if inventoryItem is not also a Weapon, it will result in a “null” – and it will not cause an error on the line that performs the cast.

      Let me know if that doesn’t work, or if you have any questions.

  4. Hello, im not sure if your still active on this lesson but im confuded on what you mean by

    NOTE: In the video, the Quest class is missing the RewardItem property from the last lesson (shown at 6:52). You should keep that property in your class.

    1. Hello Joe,

      In the source code on this page, the Quest class has a RewardItem property on line 17. If you watch the video, that line is missing from the Quest class. Some people noticed the property was missing in the video, and wondered if the video was correct or the source code was correct – whether or not Quest needs the RewardItem property. It does need it. So, you need to use the Quest.cs code from this page (not what you see in the video).

      Is that clear?

  5. Hey there I would just like to thank you for this awesome guide! I’m so happy I found this! Hope you’re having a great day, wish you all the best! – Skafti from Iceland

  6. Hello Scott(Mr Lilly), thanks for this tutorial. Your said on this chapter some that “There are different ways to do this,…” meaning there could be other ways to store information about Player Quest for instance or Loot Item. What could be those other ways to do that, because in OOP, they say “nouns” (like you pointed out) and “nouns-phrase” become classes. If it is easy to identify “LootItem” from the scenario, but not the same to identify other “nouns-phrases” like Player Quest, what could be the other ways, why not just create collection/list of Quests in the Player Class and so and so on. Thank for your answer

    1. Hello Kevin,

      This is one of the parts of programming that requires “abstract thinking”. We start with the simple classes that relate to the nouns. But, many programs will require other classes that are not so simple.

      A Quest object (for example) will hold the information about a quest – its name, what must be done to complete the quest, what the rewards are, etc. But, the program also needs to track the “state” of a Quest object (has the Player completed the Quest?) For a simple game, with one Player, we could just add a Completed property to the Quest class, and the Player could have a property that contains Quest objects, instead of PlayerQuest objects. When the Player receives a Quest, we instantiate the Quest object and give it to the Player.

      But, if we were writing a multi-player game, it might be more complex. In the game world, each quest would only have one Quest object. When a Player receives a Quest (let’s use the “kill snakes” quest for this example), each Player would only have a reference to that one “kill snakes” quest object. Then, if we needed to change something about the Quest object (for example, the reward), we would only need to change the one “kill snakes” Quest object that every Player has a reference to (instead of looking at each Player, checking if they have the Quest, and updating their Quest object’s reward if they have not completed the Quest). This is what we are doing in our game. Our World have one instance of each Quest object, and all the Players (in our game, it is only the one Player) have a PlayerQuest object that has a reference to the World’s single “kill snakes” Quest object.

      Does that help answer your question?

  7. Is there a reason why we’re using Lists instead of other types that can store multiple things like arrays or dictionary(not sure if C# has this)?

    1. I generally use Lists so I can easily use LINQ. To me, LINQ lets you write code that sounds similar to normal language (for example, if I was working with a list named “items”, I could write “items.Where(item => item.Value > 10).OrderBy(item => item.Name)”

      Dictionaries are good when I have objects with a unique value that I can use for the “key”. ANd I do use them in other programs, But, because this is a beginner’s guide, I wanted to keep it simple and just use one type of collection class.

  8. So i’ve been following along this far and i may have missed it but why are we doing this?

    public LootItem(Item details, int dropPercentage, bool isDefaultItem)

    Details = details;
    DropPercentage = dropPercentage;
    IsDefaultItem = isDefaultItem;

    Why name it one thing then go and name it the same thing with lowercase?

    1. Hi Caleb,

      I’m sorry it took so long to respond. C# is case-sensitive. So, “details” is different from “Details”. In this case, “details” is the name we use for the parameter – the temporary value being passed into the LootItem constructor. “Details” is the name of the property – the permanent place where we hold the value in the object.

      Most C# programmers follow this pattern. Constructor parameters are the same name as the property they are put into, except the parameter is camel-cased (starts with a lower-case letter) and the property is Pascal-cased (starts with an upper-case letter). https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions#capitalizing-compound-words-and-common-terms

Leave a Reply

Your email address will not be published. Required fields are marked *