sizeof()与Marshal.SizeOf()的不同

在.NET中一般都是通过sizeof()或Marshal.SizeOf()来获取数据类型的大小,来简要地看一下它们二者有何不同。

sizeof()

sizeof()在MSDN中的介绍是,在编译时获得一个数据类型的确定大小,并且被指定为一个常量。如果试图把它用在无效类型上则会出现编译错误,见CS0233

也就意味着在运行阶段它是没有开销的。

例子

1 sizeof(int)

编译成IL则为:

ldc.i4.4 

 

Marshal.SizeOf()

在System.Runtime.InteropServices.Marshal.SizeOf(),MSDN介绍是,总是在运行时计算结构化数据类型的大小。

这就是说,像装箱或者计算大小的开销在该方法被调用时。

例子

Marshal.SizeOf<int>()

编译成IL则为: 

call        System.Runtime.InteropServices.Marshal.SizeOf<Int32>

 

一窥究竟

我们可以看看源码 (referencesource)

 1 //====================================================================
 2 // SizeOf()
 3 //====================================================================
 4 [ResourceExposure(ResourceScope.None)]
 5 [System.Runtime.InteropServices.ComVisible(true)]
 6 public static int SizeOf(Object structure)
 7 {
 8     if (structure == null)
 9 throw new ArgumentNullException("structure");
10     // we never had a check for generics here
11     Contract.EndContractBlock();
12  
13     return SizeOfHelper(structure.GetType(), true);
14 }
15  
16 public static int SizeOf<T>(T structure)
17 {
18     return SizeOf((object)structure);
19 }
20  
21 [ResourceExposure(ResourceScope.None)]
22 [Pure]
23 public static int SizeOf(Type t)
24 {
25     if (t == null)
26 throw new ArgumentNullException("t");
27     if (!(t is RuntimeType))
28 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "t");
29     if (t.IsGenericType)
30 throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t");
31     Contract.EndContractBlock();
32  
33     return SizeOfHelper(t, true);
34 }
35  
36 public static int SizeOf<T>()
37 {
38     return SizeOf(typeof(T));
39 }
40  
41 [ResourceExposure(ResourceScope.None)]
42 [MethodImplAttribute(MethodImplOptions.InternalCall)]
43 internal static extern int SizeOfHelper(Type t, bool throwIfNotMarshalable);

从上面可以看出这个Marshal.SizeOf()方法依赖SizeOfHelper这个外部方法的引用,如果数据类型有提供则在外部执行计算。如果是结构体装箱为对象,则把该对象当参数传入。

注意事项

如下Marshal.SizeOf<T>() 与sizeof(T)的一些类型,计算出大小的结果

1 Marshal.SizeOf<Boolean>(): 4
2 sizeof(Boolean): 1
3 Marshal.SizeOf<Char>(): 1
4 sizeof(Char): 2

看这些相同类型下,在.Net中被封送处理成非托管的数据类型时,原托管类型2个字节的Char计算成了Windows系统类型中的1个字节的SBYTE,而托管类型1个字节的Boolean计算成了Windows系统类型中的4个字节的BOOL。

(原文引自:sizeof() vs Marshal.SizeOf()

posted on 2018-04-01 19:00  Bean.Hsiang  阅读(2198)  评论(0编辑  收藏  举报