I was surprised recently to discover that the compiler is apparently not strict about comparing interface references and am wondering why it works this way.
Consider this code:
class Program
{
    interface I1 {}
    interface I2 {}
    class C1 : I1 {}
    class C2 : I2 {}
    static void Main(string[] args)
    {
        C1 c1 = new C1();
        C2 c2 = new C2();
        I1 i1 = c1;
        I2 i2 = c2;
        bool x = c1 == c2;
        bool y = i1 == i2;
    }
}
The compiler says that I can't compare c1 == c2, which follows. The types are totally unrelated. Yet, it does permit me to compare i1 == i2. I would expect it to error here with a compile-time failure but I was surprised to find out that you can compare any interface to any other and the compiler will never complain. I could compare, for example (I1)null == (IDisposable)null and no problem.
Are interfaces not objects? Are they a special type of reference? My expectation would be that a == would result in either a straight reference compare or a call into the concrete class's virtual Equals.
What am I missing?