C# 接口的内存分配

C# 接口的内存分配,c#,memory-management,C#,Memory Management,我知道接口不能被实例化,但如果我们把它分配给一个对象,谁能解释一下内存是如何分配给它的。例如: ITest obj = (ITest) new TestClass1(); //TestClass1 is a class which implements ITest obj.MethodsDefinedInInterface(); ITest是否转换为对象以保存TestClass1的属性和方法。内存被分配给实现接口的对象,就像任何其他对象一样。它是否实现接口只是对象的一个属性内存只分配给Tes

我知道接口不能被实例化,但如果我们把它分配给一个对象,谁能解释一下内存是如何分配给它的。例如:

ITest obj = (ITest) new TestClass1();  //TestClass1 is a class which implements ITest
obj.MethodsDefinedInInterface();

ITest是否转换为对象以保存TestClass1的属性和方法。

内存被分配给实现接口的对象,就像任何其他对象一样。它是否实现接口只是对象的一个属性

内存只分配给
TestClass1
实例。接口
ITest
只是一种引用类型,它指向分配的内存。

它应该类似于:

TestClass1 test = new TestClass1();  
ITest obj = (ITest) test;
obj.MethodsDefinedInInterface();
我想这回答了你的问题

ITest是否转换为对象以保存TestClass1的属性和方法


ITest是一种类型。TestClass1属性和方法仍然存在,只是您无法通过obj变量访问它。

它非常简单。为TestClass1分配,然后将其转换回接口。请注意,您不是在实例化接口,而是在实例化一个实现接口的类,然后调用在具体类中实现(强制)的接口方法

另一种说法是:

TestClass1 test = new TestClass1();
ITest obj = (ITest) test;
obj.MethodsDefinedInInterface();

请注意,分配的区域用于TestClass1!它不会因为铸造而生长或收缩

接口
只需确保对象在编译时在技术和逻辑上都符合cerain标准

在执行代码和使用接口时,将分配内存,就像您将使用类实例化对象一样

所以在内存分配方面,两者之间没有区别


我不太清楚你所说的“分配”到底是什么意思。以下语句构成两个独立的“分配”:

TestClass1 test = new TestClass1();
ITest test = new TestClass1();
首先是
newtestclass1()
语句,它在堆上分配sizeof(TestClass1)。其次,堆分配地址的分配存储在变量
test
中,该变量在堆栈上分配为sizeof(object*)(即IntPtr.Size,或基于硬件+操作系统+软件运行的32/64位)

“分配”中的以下语句完全相同:

TestClass1 test = new TestClass1();
ITest test = new TestClass1();
这两种方法之间的唯一区别是可对变量
test
调用的方法

注意:对于实现接口的结构,情况并非如此。接口必须是引用类型,正如您所知,结构不是。这在.NET中称为装箱(boxing),通过首先将结构的副本放在堆上,可以将结构作为引用类型进行引用

因此,我们现在重新评估该声明:

TestSTRUCT1 test2 = new TestSTRUCT1();
这将在堆栈的命名变量test2上“分配”sizeof(TestSTRUCT1)。(不确定分配给
newteststruct1()
的影响是什么,它可能会创建额外的堆栈副本,但应该在分配后立即删除

如果我们随后将此值分配给接口:

ITest test3 = test2;

我们现在又进行了两次分配。首先将结构复制到堆中。然后将该堆驻留结构的地址放入新“分配”的变量
test3
(在堆栈上)因此,首先,当您输入此方法时,将在堆栈上为所有参数(如果适用)、返回值(如果适用)以及该方法的所有局部变量分配空间。因为我们在这里显示的是,唯一需要分配的局部变量是
obj
obj
是一个接口,因此需要足够的空间单个引用的空间(32位系统上为32位,64位系统上为64位)。由于没有其他局部变量、返回值或参数,我们将只占用堆栈上的一个字

因为我们正在分配一个对象(
newtestclass1()
),并假设该对象是一个类(而不是一个
struct
,因为命名一个
struct
TestClass1
将非常简单)将在堆上分配足够的空间来说明
TestClass
的单个实例。该空间将足够容纳每个字段(无论可访问性如何)再加上一些额外的对象开销。对这个新分配的对象的引用将出现在为我们的局部变量分配的堆栈上


这一切都忽略了处理器在运行时使用的寄存器;由于编译器、抖动、操作系统、处理器硬件等的复杂转换和优化,我无法开始尝试预测这将需要什么。幸运的是,由于所有这些抽象,我真的不需要在意。

想想看他的方式;一套建筑图纸在一栋完工的建筑中占用了多少空间?当然没有;它们只用于建筑,而不是建筑本身的一部分。类、接口和结构定义也是如此。只有对象需要内存。感谢您的回复。感谢您。想想接口吧e作为契约。如果对象实现和接口。实际上,它同意通过实现接口中描述的所有属性/事件/方法来遵守契约。接口本身从未构造,也从未分配任何内存。实例化后的对象被构造并分配内存。这就是这不是真的。接口变量将导致为对象的实际实例的引用分配内存。引用需要非零内存量。现在,如果您只讨论堆分配,那么这可能适用,但这是一个完全不同的问题。这就是我所说的-OP有一个引用(分配给已分配内存)在堆栈上(32位系统上为4字节)。此引用是否具有类型
TestClass1
ITest
、或
对象
,感谢您提供内存分配的低级详细信息。