• 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()

  • 相关阅读:
    动软代码生成器 修改配置
    显示转换explicit和隐式转换implicit
    Memcache学习整理
    SQL2008-分页显示3种方法
    SQL2008-表对表直接复制数据
    SQL2008-删除时间字段重复的方法
    SQL2008-中不想插入从复记录
    SQL2008-c:PROGRA~1COMMON~1SystemOLEDB~1oledb32.dll出错找不到指定的模块
    ACCESS-如何多数据库查询(跨库查询)
    ACCESS-字符函数
  • 原文地址:https://www.cnblogs.com/BeanHsiang/p/8687751.html
Copyright © 2020-2023  润新知