接口变量是否具有值类型或引用类型语义?

pho*_*oog 10 .net c# interface value-type reference-type

接口变量是否具有值类型或引用类型语义?

接口按类型实现,这些类型是值类型或引用类型.显然,这两个intstring实现IComparable,并且int是一个值类型,并string为引用类型.但是这个怎么样:

IComparable x = 42;
IComparable y = "Hello, World!";
Run Code Online (Sandbox Code Playgroud)

(我试图回答的问题可能被删除了,因为它询问接口是存储在堆栈还是堆中,而且,正如我们都应该知道的那样,考虑到它们之间的值和引用类型之间的差异更具建设性.语义而不是它们的实现.有关讨论,请参阅Eric Lippert的堆栈是一个实现细节.)

Mar*_*ell 14

通常,根据现有的答案,它是一个参考类型,需要拳击; 但有一个例外(总是不存在吗?).在一个泛型方法where约束,也可以是两个:

void Foo<T>(T obj) where T : ISomeInterface {
    obj.SomeMethod();
}
Run Code Online (Sandbox Code Playgroud)

这是一个受约束的操作,即使它是值类型也不会装箱.这是通过constrained.相反,JIT执行操作作为引用类型的虚拟调用,以及对值类型的静态调用.没拳击.


pho*_*oog 6

类型为 的变量或字段IComparable是引用类型变量或字段,无论分配给该字段的值的类型如何。这意味着x示例代码中是装箱的。

一个简单的测试就可以证明这一点。该测试基于以下事实:您只能将值类型拆箱为其原始类型(以及该类型的可为空版本)

    [TestMethod, ExpectedException(typeof(InvalidCastException))]
    public void BoxingTest()
    {
        IComparable i = 42;
        byte b = (byte)i;      //exception: not allowed to unbox an int to any type other than int
        Assert.AreEqual(42, b);
        Assert.Fail();
    }
Run Code Online (Sandbox Code Playgroud)

编辑

除此之外,C# 规范还专门将引用类型定义为包含类类型、接口类型、数组类型和委托类型。

编辑2

正如 Marc Gravell 在他的回答中指出的那样,具有接口约束的泛型类型是一种不同的情况。这不会引起拳击。


Ebe*_*eer 5

这是关于理解类型的装箱和拆箱.在您的示例中,int在赋值时被加框,并且对该"box"或对象的引用是分配给x的内容.值类型int被定义为实现IComparable的结构.但是,一旦使用该接口引用引用值类型int,它将被装箱并放在堆上.这就是它在实践中的运作方式.使用接口引用导致装箱按定义发生的事实使得此引用类型语义.

MSDN:拳击和拆箱

  • phoog是对的.只有类实现接口的想法是完全错误的.结构和数组不是类,但它们也实现接口.(当然,接口继承自其他接口.) (2认同)