我遇到了一个值类型正在实现ref的scenerio。类型。
只是想知道怎么可能(幕后背后是什么?)
struct是值类型,接口是ref。类型但结构可以实现接口而没有任何错误...
有什么想法? 提前致谢
答案 0 :(得分:9)
实际上,它同时以两种不同的方式实现。
首先,任何值类型都可以装入引用类型的对象实例中。这个盒子是由运行时按需发明的,它将以你期望的方式实现接口 - 即盒子将实现值类型实现的任何接口。
但是,CLI也允许“受限制的呼叫”。约束调用将虚拟调用转换为静态调用,但仅限于值类型通过覆盖或接口实现实现实例方法的情况(否则它由JIT实现为虚拟调用)。特别是泛型广泛使用约束调用(受限制的操作码与泛型一起添加,正是出于这个原因)。
答案 1 :(得分:2)
接口不是引用类型,它只是如何实现类型的合同。
接口类型的变量必须是引用,因为实现接口的类型可以是引用类型。接口类型的变量必须能够保存引用类型或值类型,因为两者都可以实现接口。值类型可以加框,以便它获得引用,但引用类型不能“展平”为值。
答案 2 :(得分:1)
虽然我们都使用单词Type来引用接口,实际上,即使MSDN文档将接口描述为引用类型,接口也不是与任何其他引用类型具有相同意义的类型或任何价值类型。从某种意义上说,它根本不是一种类型。它是一个行为(一组方法,属性和事件)的契约,类型必须通过声明实现该接口来包含。
public interface ITestInterface { }
public class MyClass:ITestInterface { }
ITestInterface m = new MyClass() as ITestInterface;
var t = m.GetType();
即使变量m
被声明为ITestInterface
类型,您也会看到,类型变量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
包含指向描述的两个表的指针 该类型支持的所有接口。isinst
和castclass
[CLR] 操作码使用这些表中的一个来确定类型是否支持a 给定界面。这些表中的第二个是接口偏移量 CLR在调度虚拟方法调用时使用的表 反对基于接口的对象引用。
从这些引用中可以清楚地看出,接口是一种与引用类型(类)或值类型(结构)完全不同的东西。在.Net中实例化或使用的每个对象(引用类型)或值类型必须是类或结构的具体实例。 CLR加载的每个对象或结构都引用了为该类或结构的具体类型创建的单个CORINFO_CLASS_STRUCT。 Intefaces是类型的类别,定义为保证声明在该类别中的任何类或结构(声明为实现该接口)必须包含声明的每个成员的类型成员(方法,属性,事件等)。接口定义。
答案 3 :(得分:0)
接口不是类和结构的意义上的类型!接口本身不存在;所以它们既不是引用类型也不是值类型。您可以为引用指定null。但是,如果实现者类型是值类型,当您将该类型的变量分配给另一个类型时,它的行为类似于值类型。因此它的行为类似于引用类型的引用类型。
类和结构是数据(代码)的类型,但接口是类型的类型。它们可用于分类其他类型。他们强迫其他类型遵循协议,仅此而已。它们只是一种布局,一种定义,一种契约;不是现有的东西。