Click here to Skip to main content
15,789,776 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
How does this code work without an explicit cast?
<pre lang="c#">static void Main()
            IList<Dog> dogs = new List<Dog>();
            IEnumerable<Animal> animals = dogs;

I am talking about this line: "IEnumerable<animal> animals = dogs;"
You can see here that I am able to pass the variable dogs without an explicit cast. But how is this possible? Why did the compiler allow me do this? Shouldn't I first do the cast like this:

"IEnumerable<animal> animals = (List<dogs>) dogs;"
The code will work with the explicit cast and without the explicit cast but I cannot understand why it allowed me to assign dogs to the animals reference variable without an explicit cast.

What I have tried:

Trying to understand what's going on with the code.
Updated 1-Apr-18 8:11am

Assuming that you have code like this somewhere:
public class Animal { ... }
public class Dog : Animal { ... }

Then you know that a Dog is an Animal - so you can assign a Dog instance to any variable which can contain a Dog or an Animal:
Dog dog = new Dog();
Animal animal = dog;
And you probably know that IList<T> includes IEnumerable<T> among other interfaces: IList<T> Interface (System.Collections.Generic)[^]
So any variable which can contain an IEnumerable<T> can contain an instance of any class instance which implements it, and IList<T> does.
Therefore, provided the subordinate T class is also compatible, no cast is required as the type isn't changing at all.
Share this answer
The_Unknown_Member 1-Apr-18 7:12am    
But the reference variable that points to a list of dogs is the interface "IList<dog>" so I am supposed to do an explicit cast to assign the list to the IEnumerable<animal> reference. But actually it works??
See this example:
static void Main()

IAnimal a = new Dog();


static void Bark(Dog d)
Console.WriteLine("Baau baaau :@@@");

"Bark(a);" this code won't work unless I cast the argument explicitly to Dog.
OriginalGriff 1-Apr-18 7:32am    
It works because a Dog is an Animal - but your "new code" doesn't because not every Animal is a Dog (some might be a Cat, others a Horse).
When you write this:
static void Bark(Dog d)

You are telling the Bark method that it must only accept Dog parameters.
If your code worked, I could do this:
IAnimal a = new Dog();
a = new Horse();

And then the method would fail at runtime because the Horse class is not convertible to a Dog (except in the sense of going via "dog food" of course...)
Think about it:
If your method did something Dog specific with the parameter:
static void Bark(Dog d)
and you could pass it any Animal then what would happen when you passed a Cat instance, and tried to teach it to Fetch a stick?

This works because probably the Dog class is derived from the Animal class. Making the Dog an Animal.
public class Animal{}
public class Dog : Animal {}

This means that in a collection of Animal, we can always put a Dog.

All dogs are animals, but not all animals are dogs.
Now, if we were to introduce a Cat
public class Cat : Animal {}
We can also insert this Cat into a collection of Animal. Because it is an Animal.
We will not be able though to put just any Animal in a collection of Dog, because that would mean that we could just put a Cat in there. That's why we would need to cast an object to a Dog to do so.
var dog = new Dog();
var cat = new Cat();
var animals = new List<Animal>();

animals.Add(dog); //works
animals.Add(cat); //works

var dogs = new List<Dog>();
dogs.Add(dog); //works
dogs.Add(cat); //fails

HTH Christiaan
Share this answer
Share this answer

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900