带引用成员的struct:heap还是stack?

Max*_*Max 5 .net c# memory-management

众所周知,a struct是一个值类型,因此被分配在堆栈上(例如,在类中装箱的特定情况除外).

但是让我们考虑一下struct:

public struct TestStruct
{
    public List<int> items;
}

internal class Program
{
    private static void Main(string[] args)
    {
        TestStruct g;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们TestStruct g不是类的成员,而是Main函数中声明的"独立"变量.它符合stack分配变量的要求.

但是,如果我写:

g.items = new List<int>();
Run Code Online (Sandbox Code Playgroud)
  1. 我想items是分配的heap不是吗?是否g"走出去"的heap呢?
  2. 超出范围itemsg会发生什么(即 GC必须完成其工作items)?
  3. 如果不是List<int>我们有一个实现类型的变量IDisposable,那么最佳的行动方案是什么呢?

PS:我知道可以(应该?)class在这种情况下使用a 而不是a struct.我只是对这个具体案例感到困惑.

Ser*_*kiy 6

我想在堆上分配的项目不是吗?

是.items将在堆上分配内存.

g还会在堆上"走"吗?

不,struct保持在堆栈上.它只有一个字段,它items在堆上保存对列表的引用.

当g超出范围时(即GC是否必须为项目执行工作),项目会发生什么?

如果g超出范围,则items在应用程序根目录中将不会引用.项目将变为垃圾,并将在下一次垃圾收集期间由GC收集.在此之前,items将保留在内存中(当您退出使用它的方法时,将删除struct实例).

如果我们有一个实现IDisposable的类型变量而不是List,那么最佳的行动方案是什么呢?

最佳操作是IDisposable由您的结构实现.更新:实际上正如@MarcGravell指出的那样 - 如果可能的话,最好不要在这种情况下使用struct.

  • IMO,有一个实现`IDisposable`的结构是一个非常糟糕的主意; 没有好处可以来.如果需要将它实现为无操作以满足某些通用约束,那么可能.但对于实际的功能代码?非常不可靠. (2认同)