Why can't I cast from a List<MyClass> to List<object>?

Solution 1:

The reason this is not legal is because it is not safe. Suppose it were legal:

List<Giraffe> giraffes = new List<Giraffe>();
List<Animal> animals = giraffes; // this is not legal; suppose it were.
animals.Add(new Tiger());  // it is always legal to put a tiger in a list of animals

But "animals" is actually a list of giraffes; you can't put a tiger in a list of giraffes.

In C# this is, unfortunately, legal with arrays of reference type:

Giraffe[] giraffes = new Giraffe[10];
Animal[] animals = giraffes; // legal! But dangerous because...
animals[0] = new Tiger(); // ...this fails at runtime!

In C# 4 this is legal on IEnumerable but not IList:

List<Giraffe> giraffes = new List<Giraffe>();
IEnumerable<Animal> animals = giraffes; // Legal in C# 4
foreach(Animal animal in animals) { } // Every giraffe is an animal, so this is safe

It is safe because IEnumerable<T> does not expose any method that takes in a T.

To solve your problem you can:

  • Create a new list of objects out of the old list.
  • Make the method take an object[] rather than a List<object>, and use unsafe array covariance.
  • Make the method generic, so it takes a List<T>
  • Make the method take IEnumerable
  • Make the method take IEnumerable<object> and use C# 4.

Solution 2:

You can't cast List<OneType> to List<OtherType> as it is actually the instances of the list you want to cast, as well as the List itself.

there is an extension method which will allow you to do this (MSDN reference):

IEnumerable<Object> myNewEnumerable = myEnumerable.Cast<Object>();

This method will attempt to cast each instance of the list of one type to the other type and add them to a new enumerable. it will throw an exception if any instance can't be cast.

As far as the system is concerned the two types for your lists are just different types, so it is like saying:

A objectOfTypeA;
B objectOfTypeB = (B) objectofTypeA;

To be able to do the cast there would have to be an implicit or explicit conversion between the types available, which there isn't (unless you provided one, which you might be able to do).

you expect it to work because List<object> will always be able to hold any type in another list, but when you think about it in those terms you can see why it doesn't.

I'm sure there is a more technically competent answer, but that is the gist of it I think.

you might be interested in reading Eric Lippert's series on Covariance and Contravariance as this may be helpful to you.

This question may also be useful