0

I have base class that is called Entity. Then I have two child class Tag, and Property that inherits from Entity. Now I want to have dictionary that stores a List of Entity. But I cannot get it to work. Have a done the inheritance wrongly?

Dictionary<string, List<Entity>> baseDict = new Dictionary<string, List<Entity>>();

List<Tag> tags = new List<Tag>();
tags.Add(new Tag("2012"));
tags.Add(new Tag("hello"));
tags.Add(new Tag("lego"));
List<Properties> properties = new List<Properties>();
properties.Add(new Properties("Year"));
properties.Add(new Properties("Phrase"));
properties.Add(new Properties("Type"));

baseDict.Add("Tags", tags);
baseDict.Add("Properties", properties);
starcorn
  • 8,261
  • 23
  • 83
  • 124

3 Answers3

5

This is a common mistake.

A List<Derived> does not automatically inherit from a List<Base>, and they cannot be used interchangeably. The reason for this is that a list is a mutable structure, i.e. elements can be added, removed, and modified.
For example, if I have a List<Dog> and a List<Cat> lists, and I was able to treat them as a List<Mammal>, then the following code will be possible:

List<Dog> dogs = new List<Dog>();  //create a list of dogs
List<Mammal> mammals = dogs;   //reference it as a list of mammals
List<Cats> cats = mammals;  // reference the mammals as a list of cats (!!?!)
Cat tabby = new Cat();
mammals.Add(tabby)   // adds a cat to a list of dogs (!!?!)

However, if you do not need lists, just collections, (and you use C# 4 or later), you could define the dictionary as Dictionary<string, IEnumerable<Entity>>. WIth an IEnumerable it is not possible to add or modify the collection, just enumerate it, so any funny bussiness is by definition dissalowed. This is called Generic Type Covariance, and if you would like to read more on the subject, there are several great Eric Lippert blogs.

SWeko
  • 30,434
  • 10
  • 71
  • 106
3

You have a Dictionary which holds a List<Entity> per key (string). You need to store the the List<Tag/Properties> as Entities itself.

Dictionary<string, List<Entity>> baseDict = new Dictionary<string, List<Entity>>();

List<Entity> tags = new List<Entity>();
tags.Add(new Tag("2012"));
tags.Add(new Tag("hello"));
tags.Add(new Tag("lego"));

List<Entity> properties = new List<Entity>();
properties.Add(new Properties("Year"));
properties.Add(new Properties("Phrase"));
properties.Add(new Properties("Type"));

baseDict.Add("Tags", tags);
baseDict.Add("Properties", properties);
RvdK
  • 19,580
  • 4
  • 64
  • 107
1

It will work if you use Dictionary<string, IEnumerable<Entity>> instead.

The reason you cannot use a List<Tag> where a List<Entity> is expected, is that it would be dangerous to have something that looks like a List<Entity> (meaning that you can add Entity objects to it), but is really a List<Tag> (which can only handle Tag objects, not instances of other Entity subclasses or instances of Entity itself). However, IEnumerable<Entity> only lets you check the contents of a collection, not add to it, and it is safe to say that everything inside a List<Tag> is an Entity.

Aasmund Eldhuset
  • 37,289
  • 4
  • 68
  • 81