众所周知,struct
是value type,因此在堆栈上分配(例如,在类中装箱的特定情况除外)。
但请考虑一下struct
:
public struct TestStruct
{
public List<int> items;
}
internal class Program
{
private static void Main(string[] args)
{
TestStruct g;
}
}
我们的TestStruct
g
不是班级的成员,而是一个&#34;独立的&#34; Main
函数中声明的变量。它符合stack
- 已分配变量的要求。
但是,如果我写:
g.items = new List<int>();
items
已分配heap
了吗?是g
&#34;去&#34;
还在heap
上?items
超出范围时,g
会发生什么?
GC
必须为items
)工作吗?List<int>
我们有一个类型的变量怎么办?
实施IDisposable
,最佳的行动方案是什么? PS:我知道在这种情况下可以(应该?)使用class
而不是struct
。我只是对这个具体案例感到困惑。
答案 0 :(得分:6)
我认为在堆上分配的项目不是吗?
是。 items
的内存将在堆上分配。
g&#34; go&#34;在堆上也是?
不,struct停留在堆栈上。它只有一个字段,它在堆上保存对items
列表的引用。
当g超出范围时(例如GC有),项目会发生什么 做项目的工作)?
如果g
超出范围,则应用程序根目录中将不会引用items
。项目将变为垃圾,并将在下一次垃圾收集期间由GC收集。在此之前items
将保留在内存中(当您使用它时退出方法将删除结构实例)。
如果不是List,我们有一个实现类型的变量 IDisisposable,什么是最好的行动方案?
最佳操作是通过结构实现IDisposable
。更新:实际上正如@MarcGravell指出的那样 - 如果可能的话,最好不要在这种情况下使用struct。
答案 1 :(得分:4)
因此被分配在堆栈上(例如,在类中装箱的特定情况除外)。
错了。它被分配为声明范围的一部分。可能有更多的场景,它实际上在堆上而不是堆栈上(简单地说:作为另一个对象的一部分 - 而不是对象本身),所以这不是一个好的规则。
针对您的具体问题:
items
引用的对象(new List<int>()
)在堆上; 字段 items
是struct
的一部分,其中任何地方都是(并且只保存引用 - 本质上是一个美化的指针)TestStruct
实例,那么然后最好的选择是TestStruct
实际上是class
实现IDisposable
,并且来自班级Dispose()
Dispose()
醇>
作为额外的想法:能够向我写g.items = new List<int>();
表明这是struct
的一个非常糟糕的选择,因为可变性和struct
不能很好地一起玩(有很多)意外的错误可能)。之一:
struct
不可变(即readonly
字段,在自定义构造函数中初始化)class
在任何一种情况下:public
字段都是不错的选择 - 它应该是一个get
(可能是set
的属性,如果它是class
} - 但可能不是,如果它仍然是struct
)
示例:
public struct TestStruct {
private readonly List<int> items;
public List<int> Items { get { return items; } }
public TestStruct(List<int> items) {
this.items = items;
}
}
或:
public sealed class TestClass : IDisposable {
private SomeDisposable items = new SomeDisposable();
public SomeDisposable Items { get { return items; } }
public void Dispose() {
if(items != null) {
items.Dispose();
items = null;
}
}
}