为什么可以在没有编译器错误的情况下比较无关的c#接口引用

sco*_*obi 13 c# interface

我最近惊讶地发现编译器显然对比较接口引用并不严格,并且想知道为什么它以这种方式工作.

考虑以下代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器说我无法比较c1 == c2,接下来.这些类型完全不相关.然而,它确实允许我进行比较i1 == i2.我希望它在编译时失败时会出错,但我很惊讶地发现你可以将任何接口与任何其他接口进行比较,编译器永远不会抱怨.我可以比较,例如(I1)null == (IDisposable)null,没有问题.

接口不是对象吗?它们是一种特殊的参考类型吗?我的期望是a ==会导致直接引用比较或调用具体类的虚拟等于.

我错过了什么?

And*_*zub 13

我想这是以这种方式完成的,因为你可以有一个继承两个接口的类型,对于这种情况,这种比较可能很有用:

interface I1 {}
interface I2 {}
class C1 : I1, I2 {}
Run Code Online (Sandbox Code Playgroud)

所以在第一种情况下,编译器肯定知道对象是不同的,但在第二种情况下,它们可能不是.


Eri*_*ert 12

首先,请注意Hans正在引用规范的正确部分,但他引用的规范版本中有一个与您的问题相关的拼写错误.纠正的C#4规范说:

预定义的引用类型相等运算符需要以下之一:

(1)两个操作数都是已知为引用类型或文字null的类型的值.此外, 从操作数的类型到另一个操作数的类型存在显式引用转换.

(2)一个操作数是类型T的值,其中T是类型参数,另一个操作数是文字null.此外,T没有值类型约束.

除非其中一个条件成立,否则会发生绑定时错误.

这解释了你的观察.任何两个接口之间都有明确的引用转换,因为两个不同接口的任何两个实例可以引用同一个对象.可能有一个实现I1和I2的C3类,你可以对C3的同一个实例进行参考比较,一个转换为I1,另一个转换为I2.