[Mono-dev] Array and IEnumerable

Michael Hutchinson m.j.hutchinson at gmail.com
Wed Jul 1 02:40:57 EDT 2009


On Wed, Jul 1, 2009 at 1:13 AM, Trouve Antoine<trouve.antoine at mac.com> wrote:
>>> This is incorrect. List<Subclass> cannot be cast to List<Superclass> on
>>> .NET.
>>>
>>> Some examples like this can be solved by generic
>>> covariance/contravariance in .NET 4.0. See
>>> http://themonkeysgrinder.blogspot.com/2009/02/c-4-is-now.html for some
>>> explanations. However, since System.Generic.Collections.List<T> both
>>> accepts and returns objects of type T, I don't believe it could be
>>> made variant.
>>
>> Ho, you're right. I think this behaviour has changed since .NET 2.0.
>> I've just checked and one of my old project do not compile anymore.
>> ... or I might have missed something.
>
> I have missed something and written too fast: this projects works in the
> case I use my old interfaces (e.g. IList instead of List)
> It the point explained in your link as "variance" right ? By the way I
> remember it was not supported by Mono 1.3 or something.
> I tested and it works with gmcs 2.4 (and 1.9 since I've just tested).

What I said is true for "normal" (nonvariant) generic types.

However, arrays aren't really generic types. They are treated
"specially" by the runtime, so that they can be cast to IList<T> /
ICollection<T> / IEnumerable<T>, where T is the array element type or
any supertype. Presumably your problem was a bug in this feature, in
an older version of Mono.

This is demonstrated by the following sample.

using System;
using System.Collections.Generic;

class Program
{
	class A {}
	class B : A {}

	static void Main (string[] args)
	{
		B[] foo = new B[0];
		Console.WriteLine (foo is IList<B>); // true
		Console.WriteLine (foo is IList<A>); // true

		List<B> bar = new List<B> ();
		Console.WriteLine (bar is IList<B>); // true
		Console.WriteLine (bar is IList<A>); // FALSE
	}
}


Covariance and contravariance are interesting because they make this
kind of casting possible for generic types. They're in .NET 4.0, which
is not yet released, and hence are not yet supported by Mono either.
There are plenty of explanations on the web, so I won't got into
details here.

-- 
Michael Hutchinson
http://mjhutchinson.com


More information about the Mono-devel-list mailing list