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?
First off, note that Hans is quoting the correct section of the specification, but that the edition of the specification he is quoting has a typo which is relevant to your question. The corrected C# 4 specification says:
This explains your observation. There is an explicit reference conversion between any two interfaces because any two instances of two different interfaces could be referencing the same object. There could be a class C3 which implements both I1 and I2, and you could be doing a reference comparison of the same instance of C3, one converted to I1 and the other converted to I2.