1

I have following sample code in C# that is not behaving according to what I expect. My expectation is that a derived type is implicitly cast to less derived type, and this turns out be the case with array scenario code but not with generic collections scenario code.

Since a string type is implicitly cast to object type by C#, so the code below should work for both scenarios but it doesn't.

I am assigning an array or collection of strings to an array or collection of objects in code below.

Question: Why is the generic collection not behaving like an array in code below?

jsfiddle for this code is at C# code for this question

C# code

//arrays scenario
object[] objs = new object[3];
string[] strs = new string[] {"a","b","c"};
objs = strs;//THIS WORKS

//Generic collections scenario
List<object> objects = new List<object>();
List<string> strings =  new List<string>{"a","b","c"};
objects = strings; //BUT this does not work
Sunil
  • 20,653
  • 28
  • 112
  • 197
  • 2
    Suppose it did work, and I then called `objects.Add(new HttpClient())` - what would you expect to happen? – Jon Skeet Nov 18 '17 at 10:37
  • Arrays have covariance, but ordinary `class` types do not. In particular `List` is not covariant in `T`. You can use an interface type such as `IReadOnlyList` which is covariant (`out`) in `T`. – Jeppe Stig Nielsen Nov 18 '17 at 10:38
  • Yes, that would ruin everything since you only want a certain type to be in generics collection as they are supposed to provide type-safety. Right? – Sunil Nov 18 '17 at 10:39
  • But arrays still have the "crazy" covariance even if they are read/write. In the above code, you can add `objs[0] = new HttpClient();` in the bottom, and it would be allowed _at compile-time_. That is crazy. There is a check _at run-time_ that will throw an exception. ___Edit:___ So you are correct there is a difference between arrays and `List<>` in this respect. – Jeppe Stig Nielsen Nov 18 '17 at 10:41
  • @JeppeStigNielsen, so arrays are not really type safe unlike generic List collection. C# considers the second code as incorrect so generic List is always type-safe. Is that right? – Sunil Nov 18 '17 at 10:47
  • 1
    You can say with a generic type, the type-safety is enforced at compile-time. The arrays have a different kind of type-safety because they are covariant. For every _write_ to an array entry, it is checked if the reference you try to assign to the entry, is compatible with the actual run-time type of the array. So the type-safety of arrays is sometimes only enforced when the program runs; you get this: _[`System.ArrayTypeMismatchException`](https://msdn.microsoft.com/en-us/library/system.arraytypemismatchexception.aspx): Attempted to access an element as a type incompatible with the array._ – Jeppe Stig Nielsen Nov 18 '17 at 10:56
  • 1
    [Try it online](https://tio.run/##NYs5CoAwEAD7vGJLLQSPUnyCYC8p1lUkoglkgxaSt0fj0c5BnBFTCOzQKQJakRk6a2aLmzgFwCd2o0ZoUekkvWEUUVml514CFtCAno6fVLJ@AjMsE7kYlHeAxUux7HP5DW@RpNF44UO4AA) (check the "Debug" output). – Jeppe Stig Nielsen Nov 18 '17 at 11:00
  • @JeppeStigNielsen, that makes sense. Thanks. – Sunil Nov 18 '17 at 11:02

0 Answers0