Short answer
Despite the name "implicit", implicit conversions don't apply unless the rules explicitly say they do, and the rules don't allow boxing conversions when going from IEnumerable<int> to IEnumerable<IComparable<int>>. As a simpler case, you can't go from IEnumerable<int> to IEnumerable<object> for the same reason, and that case is well documented.
Long answer
OK, first of all, why would IEnumerable<T> convert to IEnumerable<IComparable<T>> at all? This is covered in §6.1.6 (C# Language Specification 5.0):
The implicit reference conversions are:
[...]
- From any reference-type to an interface or delegate type
T if it has an implicit identity or reference conversion to an interface or
delegate type T0 and
T0 is variance-convertible (§13.1.3.2) to T.
And §13.1.3.2 says:
A type T<A1, …, An> is
variance-convertible to a type T<B1, …, Bn>
if T is either an interface or a delegate type
declared with the variant type parameters T<X1, …, Xn>,
and for each variant type parameter
Xi one of the following holds:
Xi is covariant and an implicit reference or identity conversion exists from Ai to
Bi
Since IEnumerable<T> is covariant in T, this means that if there is an implicit reference or identity conversion from T to IComparable<T>, then there is an implicit reference conversion from IEnumerable<T> to IEnumerable<IComparable<T>>, by virtue of these being variance-convertible.
I emphasized "reference" for a reason, of course. Since Version implements IComparable<Version>, there is an implicit reference conversion:
- From any class-type
S to any interface-type T, provided S
implements T.
Right, so now, why doesn't IEnumerable<int> implicitly convert to IEnumerable<IComparable<int>>? After all, int implicitly converts to IComparable<int>:
IComparable<int> x = 0; // sure
But it does so not through a reference conversion or an identity conversion, but through a boxing conversion (§6.1.7):
A boxing conversion exists from any non-nullable-value-type [...] to
any interface-type implemented by the non-nullable-value-type.
The rules of §13.1.3.2 do not allow boxing conversions in considering whether a variance conversion is possible, and there is no other rule that would enable an implicit conversion from IEnumerable<int> to IEnumerable<IComparable<int>>. Despite the name, implicit conversions are covered by explicit rules.
There is actually a much simpler illustration of this problem:
object x = 0; // sure, an int is an object
IEnumerable<object> x = new int[] { 0 }; // except when it's not
This isn't allowed for the same reason: there is no reference conversion from int to object, only a boxing conversion, and those are not considered. And in this form, there are several questions on Stack Overflow that explain why this is not allowed (like this one). To summarize: it's not that this is impossible, but to support it, the compiler would have to generate supporting code to stick the code for the boxing conversion somewhere. The C# team valued transparency in this case over ease of use and decided to allow identity-preserving conversions only.
Finally, as a matter of practical consideration, suppose you had an IEnumerable<int> and you needed an IEnumerable<IComparable<int>>, how would you get it? Well, by doing the boxing yourself:
Func<int, IComparable<int>> asComparable = i => i; // compiles to ldarg ; box ; ret
IEnumerable<IComparable<int>> x = Enumerable.Empty<int>().Select(asComparable);
Of course using Enumerable.Cast would be more practical here; I wrote it this way to highlight that an implicit conversion is involved. There is a cost to this operation, and that's just the point; the C# designers wanted this cost to be explicit.