在C#堆中是否装有静态值类型的字段?

出于好奇 - 考虑下面的例子:

public class A
{
    public static int Foo;
}

public class Program
{
    static void Main()
    {
        // The following variable will be allocated on the
        // stack and will directly hold 42 because it is a
        // value type.
        int foo = 42;

        // The following field resides on the (high frequency)
        // heap, but is it boxed because of being a value type?
        A.Foo = 42;
    }
}

我的问题是以下内容: 因为它驻留在堆上Foo字段的值 ? 或者它是在一个特殊的容器对象/内存部分中封装它,就像实例值类型字段是堆中对象的一部分?

我会假设它没有装盒,但我不确定,我也找不到任何文档。

感谢您的帮助。


CLR没有限制每个类的字段需要具有相同的存储类型。 只有实例成员在GC堆上结束。 静态成员分配在加载程序堆中。 或者在字段具有[ThreadStatic]属性的情况下在线程本地存储中。 这当然强制了静态成员由该类的每个对象的每个实例共享的合约。

顺便说一下,抖动分配存储并知道该字段的地址。 所以任何加载和存储都直接使用变量的地址。 没有额外的指针取消引用,非常有效。

所以,不,根本没有必要去填充,一个静态的int只会占用4个字节。

如果您想自己查看,请使用Debug + Windows + Disassembly窗口。 显示机器代码,您将直接使用变量的地址来查看它。 每次运行该程序时它都会是一个不同的地址,这是一种恶意软件的对策。


正如Sriram和Lee在问题的评论中给出了答案,但没有提供答案,我将总结这些发现:

不,价值不是盒装的。 值类型可以驻留在堆上,它们只有在像引用类型一样使用时才被装箱。

你也可以看到我的例子的IL代码中没有包含任何拳击:

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       12 (0xc)
  .maxstack  1
  .locals init ([0] int32 foo)
  IL_0000:  nop
  IL_0001:  ldc.i4.s   42
  IL_0003:  stloc.0
  IL_0004:  ldc.i4.s   42
  IL_0006:  stsfld     int32 StaticValueTypeFieldBoxing.A::Foo
  IL_000b:  ret
} // end of method Program::Main
链接地址: http://www.djcxy.com/p/78897.html

上一篇: Is a static value type field boxed in the heap in C#?

下一篇: If an array is used as an element in struct (C#) , where is it stored?