Why does the C# compiler allow an explicit cast between IEnumerable<T> and TAlmostAnything?

I would suppose it's because IEnumerable<T> is an interface where some implementation could have an explicit cast to Banana - no matter how silly that would be.

On the other hand, the compiler knows that List<T> can't be explicitly cast to a Banana.

Nice choice of examples, by the way!

Adding an example to clarify. Maybe we'd have some "enumerable" that should always contain at most a single Banana:

public class SingleItemList<T>:Banana, IEnumerable<T> where T:Banana {
    public static explicit operator T(SingleItemList<T> enumerable) {
        return enumerable.SingleOrDefault();
    }

    // Others omitted...
}

Then you could actually do this:

IEnumerable<Banana> aBunchOfBananas = new SingleItemList<Banana>();
Banana justOneBanana = (Banana)aBunchOfBananas;

As it's the same as writing the following, which the compiler is perfectly happy with:

Banana justOneBanana = aBunchOfBananas.SingleOrDefault();

When you say Y y = (Y)x; this cast says to the compiler "trust me, whatever x is, at runtime it can be casted to a Y, so, just do it, okay?"

But when you say

List<Banana> aBunchOfBananas = new List<Banana>();
Banana justOneBanana = (Banana)aBunchOfBananas;

the compiler can look at the definitions for each of these concrete classes (Banana and List<Banana>) and see that there is no static explicit operator Banana(List<Banana> bananas) defined (remember, an explicit cast must be defined in either the type being casted or the type being casted to, this is from the spec, section 17.9.4). It knows at compile time that what you're saying can not ever be true. So it yells at you to stop lying.

But when you say

IEnumerable<Banana> aBunchOfBananas = new List<Banana>();
Banana justOneBanana = (Banana)aBunchOfBananas;

well, now the compiler doesn't know. It very well could the case that whatever aBunchOfBananas happens to be at run time, its concrete type X could have defined static explicit operator Banana(X bananas). So the compiler trusts you, like you asked it to.