为啥 .Net 引用类型中有接口?

Posted

技术标签:

【中文标题】为啥 .Net 引用类型中有接口?【英文标题】:Why are interfaces in .Net reference types?为什么 .Net 引用类型中有接口? 【发布时间】:2011-06-06 00:28:00 【问题描述】:

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

【问题讨论】:

为什么说接口是引用类型? 嗯,我刚刚参加了 70-536 的练习考试,它说接口是引用类型之一(以及类和委托)。 @nader 它引用类型... @Mar ... 是的,我真的没有想清楚。我在想一个接口实际上什么都不是。但是实现接口的东西必须被视为引用类型...... 【参考方案1】:

要被视为结构,编译器必须在编译时知道具体类型是什么,以便在堆栈上保留正确的空间。这意味着即使一个结构实现了IFoo,那么使用:

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

那么对foo 的赋值是一个装箱操作。你可以说“编译器应该发现它只是一个 foo 并使用 'constained' 操作码”,但是在一般情况下(对foo 等进行多次分配)这不是可能(我会冒险猜测它会遇到“停止问题”)。

还有一个虚拟与静态调用的问题,但“受约束”的操作码可以解决这个问题。

基本上,接口的任何使用都必须始终被视为参考。

对此有一个例外:通用约束。

如果你有

static void DoBar<T>(T target) where T : IFoo 
    target.Bar();

这里的方法对每个值类型进行一次 JIT 处理,因此T 所需的堆栈空间是已知的;对Bar 的调用是“受约束的”,可以根据需要自动为虚拟或静态。

【讨论】:

好的,我明白了。所以 MyStruct 实现了 foo,它仍然是一个值类型。但是一旦你将 MyStruct 转换为 foo,它就会被装箱。 foo 的行为使其成为引用类型。此外, foo 可以被分配一个值类型,然后是一个引用类型,它永远不知道,所以它必须表现为一个引用类型来涵盖所有场景......这一切都正确吗?【参考方案2】:

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

【讨论】:

以上是关于为啥 .Net 引用类型中有接口?的主要内容,如果未能解决你的问题,请参考以下文章

这是引用包含泛型的 C# 接口的 VB.NET 实现的 FxCop 错误吗?

理解栈堆值类型引用类型装箱和拆箱

C# 8中的可空引用类型

为啥委托是引用类型?

引用类型 与 值类型

服务引用 - 为啥在引用的程序集中重用类型