Search code examples
c#listcastingcovariance

Why List<Parent> permits adding new Child but not assigning from List<Child>


This is probably a duplicate. But after a day of research I was hoping for your leniency. It is a question about covariance.

Why can I do this?

List<Animal> allAnimals = new List<Animal>();
allAnimals.Add(new Dog());
allAnimals.Add(new Cat());

But cannot do this?

List<Dog> aBunchOfDogs = new List<Dog>();
allAnimals = aBunchOfDogs;

I have read a few discussions on covariance.

"Covariance in C#"

"Converting lists to interface lists"

"Casting list to interface list"

My understanding is, that I cannot add a list of dogs to a list of animals because then I could add a cat to the animal list, which would be dangerous. But adding a single instance of a cat or a dog to a list of animals is just as dangerous isn't it? It seems to me that C# is undecided on whether to trust me or not.


Solution

  • Assuming you understand why you can pass a Dog and Cat instance to a method accepting Animal, here's why your latter example isn't allowed:

    List<Dog> aBunchOfDogs = new List<Dog>();
    allAnimals = aBunchOfDogs;
    allAnimals.Add(new Cat()); // Fine because allAnimals is List<Animal>
    
    foreach (var dog in aBunchOfDogs)
    {
        dog.Woof(); // The Cat can't woof
    }