1

摘自C# 5.0 in a Nutshell: The Definitive Reference in page 22;

引用类型需要为引用和对象分别分配内存。对象消耗与其字段一样多的字节,加上额外的管理开销。精确的开销本质上是 .NET 运行时实现的私有开销,但开销至少为 8 个字节,用于存储对象类型的键,以及临时信息,例如多线程的锁定状态和用于指示它是否已被垃圾收集器从移动中修复。对对象的每个引用都需要额外的 4 或 8 个字节,具体取决于 .NET 运行时是在 32 位还是 64 位平台上运行。

我不太确定我是否完全理解这个大胆的部分。它说在 32 位平台上一个引用需要四个字节,在 64 位平台上它需要八个字节。

所以,假设我们有

string s = "Soner";

如何检查此s引用需要多少字节?

4

3 回答 3

6

您可以使用Environment.Is64BitProcess. 如果是,则每个引用将是 8 个字节。如果不是,每个引用将是 4 个字节。引用的类型和它所引用的对象的内容是无关紧要的。

编辑:正如现在已删除的答案中所述,IntPtr.Size更简单。

编辑:正如评论中所指出的,虽然目前CLR 中的所有引用都是相同的大小,但它有可能在某些时候会走上与 Hotspot 类似的路径,在许多情况下它使用“压缩 oops”将引用存储为 32 -bit 值,即使在 64 位进程中(不限制可用内存)。

于 2013-07-04T19:59:52.053 回答
2

如果您真的计算参考的大小,使用它Reference.Size应该可以:

using System;
using System.Reflection.Emit;

public static class Reference
{
    public static readonly int Size = new Func<int>(delegate()
    {
        var method = new DynamicMethod(string.Empty, typeof(int), null);
        var gen = method.GetILGenerator();
        gen.Emit(OpCodes.Sizeof, typeof(object));
        gen.Emit(OpCodes.Conv_I4);
        gen.Emit(OpCodes.Ret);
        return ((Func<int>)method.CreateDelegate(typeof(Func<int>)))();
    })();
}

但是与其他答案一起使用可能是一个更好的主意。

于 2013-07-04T20:06:32.977 回答
1

要扩展 Jon Skeet 的答案,要获得可能的字节数,您应该这样做:

int bytesInRef = Environment.Is64BitProcess ? 8 : 4;

然而,这是一个实现细节。您不仅不应该担心这一点,还应该忽略这一点。这是一篇关于(另一个)实现细节的好博客文章,但它仍然适用,因为它讨论了实现细节以及你不应该如何信任它们或依赖它们。这里:堆栈是一个实现细节

于 2013-07-04T20:09:36.723 回答