在C#中,sizeof用来计算非托管类型(值类型)的大小,不能用来计算托管类型(引用类型)的大小,单位是字节。
当对引用类型进行sizeof的时候,编译后会报错,如代码:
Console.WriteLine(sizeof(string));
将会报错

一、sizeof
1、除了struct,一般的值类型可以直接使用sizeof()来计算其大小,不涉及上下文安全问题,如:
Console.WriteLine(sizeof(int));//4
具体sizeof计算结果如下:

2、至于struct,如果对其使用sizeof()则涉及上下文安全,如代码
public struct TestStruct
{
public bool TestA;
public int TestInt;
public bool TestB;
}
//用sizeof必须要挂在unsafe 代码下,而且工程属性要设置为支持上下文不安全模式
unsafe
{
Console.WriteLine(sizeof(TestStruct));
}
此时,输出的字节大小是12,并不是 1 + 4 + 1 = 6。
为啥是12呢,这就涉及到内存对齐。
内存对齐的规则可以点击这里
TestStruct对应的内存是:0xxx|0000|0xxx
如果TestB和TestInt两行对调一下,如下代码
public struct TestStruct2
{
public bool TestA;
public bool TestB;
public int TestInt;
}
此时TestStruct2所占的字节大小是8,对应的内存应该是:00xx|0000
要想TestStruct和TestStruct2所占的内存大小一样的话,可以对TestStruct使用 字段布局[StructLayout(LayoutKind.Auto)]
[StructLayout(LayoutKind.Auto)]
public struct TestStruct
{
public bool TestA;
public int TestInt;
public bool TestB;
}
至于字段布局,可以看这里
二、Marshal.SizeOf
Marshal.SizeOf返回类的非托管大小
Marshal.SizeOf的文档,参看官网
为了帮助理解,关于封送处理,可以参看这里
我测试代码如下:
using System;
using System.Runtime.InteropServices;
namespace TestCSharp
{
[StructLayout(LayoutKind.Sequential)]
public class TestClass
{
}
[StructLayout(LayoutKind.Sequential)]
public struct TestStruct2
{
public byte by;
public sbyte sb;
public bool b;
public char c;
public short s;
public ushort us;
public int i;
public uint ui;
public long l;
public ulong ul;
public float f;
public double d;
public decimal dec;
public TestClass tc;
}
internal class Program
{
public static void Main(string[] args)
{
TestStruct2 t = new TestStruct2();
t.tc = new TestClass();
Console.WriteLine(Marshal.SizeOf(t.by));//1
Console.WriteLine(Marshal.SizeOf(t.sb));//1
Console.WriteLine(Marshal.SizeOf(t.b));//4
Console.WriteLine(Marshal.SizeOf(t.c));//1
Console.WriteLine(Marshal.SizeOf(t.s));//2
Console.WriteLine(Marshal.SizeOf(t.us));//2
Console.WriteLine(Marshal.SizeOf(t.i));//4
Console.WriteLine(Marshal.SizeOf(t.ui));//4
Console.WriteLine(Marshal.SizeOf(t.l));//8
Console.WriteLine(Marshal.SizeOf(t.ul));//8
Console.WriteLine(Marshal.SizeOf(t.f));//4
Console.WriteLine(Marshal.SizeOf(t.d));//8
Console.WriteLine(Marshal.SizeOf(t.dec));//16
Console.WriteLine(Marshal.SizeOf(t.tc));//1
Console.WriteLine(Marshal.SizeOf(t));//80,#pragma pack(n) 表示设置为n字节对齐。 C#默认应该也是8字节对齐(没有查证),所以t.dec应该是按照8而不是16对齐,这个需要注意
}
}
}
这个是测试输出的字节大小

其中类的封送不能用[StructLayout(LayoutKind.Auto)],可以改成[StructLayout(LayoutKind.Sequential)]
Marshal.SizeOf所得大小也是按内存对齐规则来的
另:如果sizeof(TestStruct)没有放在unsafe下,如
Console.WriteLine(sizeof(TestStruct));
会有编译错误:

解决办法是:
unsafe
{
Console.WriteLine(sizeof(TestStruct));//用sizeof必须要挂在unsafe 代码下,而且工程属性要设置为支持上下文不安全模式
}
别忘记工程属性要设置为支持上下文不安全模式,否则会报如下编译错误:
原文:https://www.cnblogs.com/woniu89/p/12355172.html