Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: No casting within Generics?

While I can upcast a string to an object, I cannot upcast an IList of strings to an IList of objects. How come? What to do now other that coping all items to a new IList?

static void ThisWorks()
{
     IList<object> list = new List<object>();
     list.Add("I can add a string since string : object");
}

static void ThisDoesNotWork()
{
     // throws an invalid cast exception
     IList<object> list = (IList<object>) new List<string>(); 

     list.Add("I'm never getting here ... why?");
}
like image 319
Felix Alcala Avatar asked Apr 19 '09 13:04

Felix Alcala


3 Answers

This is not possible as generics are invariant (as of C# 3.0).

You can workaround it with:

var objectList = list.Cast<object>().ToList();
like image 187
mmx Avatar answered Nov 03 '22 14:11

mmx


Look at it like this: while a banana is a fruit, a basket of bananas is not a basket of fruit, since you can add oranges to the latter, but not the former. Your List<string> has stronger constraints than a List<object>.

Casting should always respect Liskow. For containers and iterators which do not admit modification, such casting is safe, but once things can be changed, you are skating close to the thin ice.

like image 25
Pontus Gagge Avatar answered Nov 03 '22 14:11

Pontus Gagge


What you asked is essentially a question of Contravariance and Covariance. It is a concept in programming language design which talks about how methods and collections behave with respect to objects of two classes in the same inheritance hierarchy. Reading the Wikipedia article may help place your above curiosity in a larger, more general perspective.

like image 36
Frederick The Fool Avatar answered Nov 03 '22 15:11

Frederick The Fool