为什么.NET中的接口是引用类型?

13

为什么接口是引用类型?据我所知,接口是类(或结构体)之间的契约,那么为什么它会成为一种类型呢?我认为它既不是值类型也不是引用类型。


为什么您说接口是引用类型? - Nader Shirazie
嗯,我刚刚在练习70-536考试,它说接口是引用类型之一(与类和委托一起)。 - richard
3
@nader 这是一个引用类型(reference type)… - Marc Gravell
@Mar... 是的,我当时确实没有想清楚。我认为接口本身并不是什么东西。但是实现接口的对象必须被视为引用类型... - Nader Shirazie
2个回答

11

要将结构体视为一种结构,在编译时必须知道具体类型,以便在堆栈上保留正确的空间。这意味着即使一个结构体实现了IFoo,也是如此。

var ms = new MyStruct();
IFoo foo = ms;

如果对foo进行赋值,那么这是一个装箱操作。你可以说“编译器应该注意到它仅仅是一个foo并使用'constrained'操作码”,但在一般情况下(多次对foo进行赋值等)这是不可能的(我猜测它会遇到“停机问题”)。
还存在虚函数调用和静态函数调用的问题,但“constrained”操作码可以解决这个问题。
基本上,接口的任何使用都必须始终被视为引用。
唯一的例外是泛型约束。
如果你有:
static void DoBar<T>(T target) where T : IFoo {
    target.Bar();
}

这里该方法被针对每种值类型进行了即时编译,因此需要的栈空间 T已知;对Bar的调用是"受限制的",可以根据需要自动变为虚拟或静态。


好的,我明白了。所以MyStruct实现了foo,它仍然是一个值类型。但一旦你将MyStruct强制转换为foo,它就会被装箱。foo的行为使它成为引用类型。此外,foo可以被分配一个值类型,然后是一个引用类型,它永远不知道,所以它必须表现为一个引用类型,以涵盖所有情况...这一切都正确吗? - richard

3

它们是引用类型,因为值类型在编译时具有固定大小,因此可以在堆栈上分配。引用类型是指针,因此指针是恒定大小的,但它们可以指向任何大小的内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接