值类型如何实现ref类型

我遇到了一个值类型正在实现ref的scenerio。 类型。

只是想知道怎么可能(幕后的是什么?)

struct是一个值类型,接口是ref。 类型但结构可以实现接口没有任何错误…

有什么想法吗? 提前致谢

实际上,它同时以两种不同的方式完成。

首先,任何值类型都可以装入引用类型的对象实例中。 此框由运行时按需发明,并将以您期望的方式实现接口 – 即该框将实现值类型实现的任何接口。

但是,CLI也允许“受限制的呼叫”。 受约束的调用将虚拟调用转换为静态调用,但仅限于值类型通过覆盖或接口实现实现实例方法的情况(否则它由JIT实现为虚拟调用)。 特别是generics广泛使用约束调用(受限制的操作码与generics一起添加,正是出于这个原因)。

接口不是引用类型,它只是如何实现类型的合同。

但是,接口类型的变量必须是引用,因为实现接口的类型可以是引用类型。 接口类型的变量必须能够保存引用类型或值类型,因为两者都可以实现接口。 可以对值类型进行装箱以使其获得引用,但不能将引用类型“展平”为值。

虽然我们都使用单词Type来引用接口,实际上,即使MSDN文档将接口描述为引用类型 ,接口也不是与任何其他引用类型或任何值类型具有相同意义的类型。 从某种意义上说,它根本不是一种类型。 它是一个行为(一组方法,属性和事件)的契约,类型必须通过声明实现该接口来包含。

public interface ITestInterface { } public class MyClass:ITestInterface { } ITestInterface m = new MyClass() as ITestInterface; var t = m.GetType(); 

您将看到即使变量m被声明为ITestInterface类型,Type变量t仍然是MyClass

因此,尽管由于历史原因我们使用单词type来应用于接口,但是接口的“类型”与具体对象的类型是一个非常不同的东西,具体对象是类或结构的实例。

引用Don Box的Essential .Net

CLR处理对象和接口类型的方式与其前身(C ++和COM)不同。 在C ++和COM中,给定的具体类型每个基类型或支持的接口都有一个方法表。 相反,CLR中给定的具体类型只有一个方法表。 通过推断,基于CLR的对象只有一个类型句柄。 这与C ++和COM形成鲜明对比,在C ++和COM中,对象通常每个基本类型或接口都有一个vptr。 因此,CLR的castclass不会以与C ++的dynamic_cast或COM的Query-Interface相同的方式产生第二个指针值。

读到这一点很明显,接口本身永远不会有vptr表,或CORINFO_CLASS_STRUCT因为只有真正的具体对象(引用和值类型)才能拥有。 此结构由CLR为运行时由执行代码加载的每个Type创建和维护。 同样,来自Essential .Net

CORINFO_CLASS_STRUCT包含指向两个表的指针,这两个表描述了该类型支持的所有接口。 isinstcastclass [CLR]操作码使用这些表中的一个来确定类型是否支持给定的接口。 这些表中的第二个是CLR在调度针对基于接口的对象引用进行的虚方法调用时使用的接口偏移表。

从这些引用中可以清楚地看出,接口是一种与引用类型(类)或值类型(结构)根本不同的东西。 在.Net中实例化或使用的每个对象(引用类型)或值类型必须是类或结构的具体实例。 CLR加载的每个对象或结构都引用了为该类或结构的具体类型创建的单个CORINFO_CLASS_STRUCT。 Intefaces是类型的类别,定义为保证声明在该类别中的任何类或结构(声明为实现该接口)必须包含声明的每个成员的类型成员(方法,属性,事件等)。接口定义。

在类和结构的意义上,接口不是类型! 接口本身不存在; 所以它们既不是引用类型也不是值类型。 您可以为引用指定null。 但是,如果实现者类型是值类型,当您将该类型的变量分配给另一个类型时,它的行为类似于值类型。 因此它的行为类似于引用类型的引用类型。

类和结构是数据(代码)的类型,但接口是类型的类型。 它们可用于分类其他类型。 他们强迫其他类型遵循协议,仅此而已。 它们只是一种布局,一种定义,一种契约; 不是现有的东西。