1

Question: Why can't i add an Array of Integers to a List<Object>?

following the posts:

do-value-types-integer-decimal-boolean-etc-inherit-from-object

how-do-valuetypes-derive-from-object-referencetype-and-still-be-valuetypes

i'm understanding the following structure:

Integer => Inherits => System.ValueType => Inherits => System.Object

Then why am i getting an error when i do the following:

 List<object> myObjects = new List<object>();
 myObjects.AddRange(IntegerArray.ToList());

Given Error:

cannot convert from 'System.Collections.Generic.List<int>' to
'System.Collections.Generic.IEnumerable<object>

This one works though:

 List<int> myObjects = new List<int>();
 myObjects.AddRange(IntegerArray.ToList());
Community
  • 1
  • 1
User999999
  • 2,500
  • 7
  • 37
  • 63
  • 1
    Check this one: [Why covariance and contravariance do not support value type](http://stackoverflow.com/questions/12454794/why-covariance-and-contravariance-do-not-support-value-type) – Ulugbek Umirov Apr 02 '14 at 09:13
  • Just curious, but why a `list`? seems a little bit dangerous to me – Sayse Apr 02 '14 at 09:14
  • `Addrange` should be `AddRange`, to start with - this clearly isn't your real code... – Jon Skeet Apr 02 '14 at 09:14

6 Answers6

4

The issue is that AddRange expects, as the error message suggests, an IEnumerable<object> and you're passing it an IEnumerable<int>. The fact that 'int' derives from object does not mean that IEnumerable<int> derives from IEnumerable<object>. If you do this then it will work because you'll be using the correct type:

myObjects.AddRange(IntegerArray.Cast<object>());
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
2

You have to explicitely say how to convert these types to each other by for example using ConvertAll, as explained here: convert a list of objects from one type to another using lambda expression.

The advantage is that it's potentially possible to convert any type.

Also look for contravariance to have an explanation on why this is: a List<Type1> cannot be casted to a List<Type2>.

Community
  • 1
  • 1
L-Four
  • 13,345
  • 9
  • 65
  • 109
1

Have you tried casting?

List<object> myObjects = new List<object>();
myObjects.AddRange(IntegerArray.ToList().Cast<object>());
Daren Thomas
  • 67,947
  • 40
  • 154
  • 200
  • @UlugbekUmirov, hm. Should probably have tested first ;-) thanks for pointing that out, I updated my answer to reflect. – Daren Thomas Apr 02 '14 at 09:15
1

Because you are not adding an array to the List<object>, but rather attempting to add each element in the array individually.

You can certainly do this, which is how the question title reads to me:

List<object> myObjects = new List<object>();
myObjects.Add(new[] { 1, 2, 3 });

However your code tells a different story, and it fails because of signature incompatibility between AddRange and the type you use to pass to it. If you have an int[] and want to add its contents to the list individually, use Cast:

myObjects.AddRange((new[] { 1, 2, 3 }).Cast<object>());
Jon
  • 428,835
  • 81
  • 738
  • 806
1

Co/Contravariance aren't allowed in C# at a collection/generics level. i.e. assignment of List<int> to List<object>

Raja Nadar
  • 9,409
  • 2
  • 32
  • 41
0

int is not object type it's primitive type. So to convert it to Object, first you need to convert it to Integer, it's wrapper class, then convert it to Object.

Also, This code requires typecasting twice. First from int to Integer. then Integer to Object which can not be done implicitly. implicit typecasting can be done by compiler only once. So it needs explicit typecasting in Object type.

garima garg
  • 308
  • 1
  • 8