我正在使用C#中的类型值,并了解到它们不像普通引用类型那样在堆上分配。如何分配具有引用类型的结构?
e.g。
struct simple{
public Employee e;
public bool topEmployee;
public void printSomething()
{
Console.WriteLine("Progress " + e.GetProgressReport());
Console.WriteLine("TopEmployee " + topEmployee);
}
};
Employee
是一个类。初始化时e
会分配给堆吗?它是否会破坏结构的意义?
答案 0 :(得分:7)
类型(值/引用)的“种类”与实例的分配方式无关。这完全取决于生命时间,并且分配的方式多于“堆”和“堆栈”。阅读The Truth About Value Types。
但是你的问题是有道理的:struct的成员类型不会影响struct实例的分配方式,因为它们不会影响对象的生命周期。顺便说一句,课程也一样。
成员e
将成为值类型对象的一部分,并在其可能的位置进行分配。该成员是引用,因此任何实际的Employee
对象e
引用将被分配到其他地方 1 。虽然听起来像是一个,但这不是一个特殊的规则; locals和类成员以及数组项的行为方式相同。它不会破坏价值类型,而是保持价值和参考类型的好处。值类型实例仍然是单独的值而不是别名,并且它们仍然具有更简单和更短的生命周期,从而可以更轻松地实现更好的分配选择。参考类型实例仍然是共享的,并且(可能)是长寿命的。
1 至少从概念上和在当前的实现中;在非常简单的情况下,优化(转义分析+分配下沉)可以合并这些分配,但我没有注意到CLR。
答案 1 :(得分:1)
结构存储器“在线”分配。类内存在堆上分配,引用(指针)分配在“内联”。
如果在程序中看到一个名为C的类变量,该变量的存储将等同于一个指针(比如4个字节),并且该类的实际存储将在堆上。
但是如果在程序中看到一个名为S的结构变量,那么该变量的存储就是声明点处变量的大小。没有堆分配存储空间。
如果C包含S,那么S将位于C的堆存储中。
如果S包含C,则对C的引用将位于S的存储中,并且C的存储位于堆上。这是关于simple
和e
。
因此,struct storage实际上可以在静态内存中,堆栈上或堆上(在类中)。类内存总是在堆上。
答案 2 :(得分:0)
引用变量“e”将在分配结构的任何地方分配(例如,未装箱的结构类型的局部变量很可能在堆栈上)。 'e'所指向的Employee实例将在堆上分配。这可能因.NET实现而异,但很可能适用于所有当前的实现。