zoukankan      html  css  js  c++  java
  • C# 如何获取某个类型或类型实例对象的大小

    在统计类型或类型实例对象时,出了个异常:

    “不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。”

    后来查了一下,原来,我们创建的struct或是class都是属于复杂类型的。(纠正一下,如果成员又有复杂类型的,而所占字节,在运行时,会有所变量,在这使用Marhsal.SizeOf也是无效的,只能对非托管资源的一个统计)

    如果不对其内部的一些成员布局设置,直接sizeof()或是Marshal.SizeOf(object), Marshal.SizeOf(Type)是会报这个异常的。

    所以我们要按需去对成员布局设置一下就可以让上面的sizeof()或是Marshal.SizeOf(object), Marshal.SizeOf(Type)正常执行。

     1、了解数据结构布局

    数据结构布局嘛,就肯定先得了解:(悲刷,百度不适合搞代码格式,还是CNBLOG好)

         // 摘要:

        //     控制当导出到非托管代码时对象的布局。

        [Serializable]

        [ComVisible(true)]

        public enum LayoutKind

        {

            // 摘要:

            //     对象的成员按照它们在被导出到非托管内存时出现的顺序依次布局。这些成员根据在 System.Runtime.InteropServices.StructLayoutAttribute.Pack

            //     中指定的封装进行布局,并且可以是不连续的。

            Sequential = 0,

            //

            // 摘要:

            //     对象的各个成员在非托管内存中的精确位置被显式控制。每个成员必须使用 System.Runtime.InteropServices.FieldOffsetAttribute

            //     指示该字段在类型中的位置。

            Explicit = 2,

            //

            // 摘要:

            //     运行库自动为非托管内存中的对象的成员选择适当的布局。使用此枚举成员定义的对象不能在托管代码的外部公开。尝试这样做将引发异常。

            Auto = 3,

        }

    Sequential 有序,可不连续,一般我们用这个。

    Explicit 这个比较少用,因为都是对成员在内存块中的位置在精确的定位的。

    Auto 这个不是很了解其上述所说的“适当的布局”,如果用这个来布局,会直接出现我上面所说的异常:

    ”不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。“

    2、了解怎么对复杂类型布局(类属性)

    要对复杂类型布局,要用到类的属性设置Attribute基类或是其派生类都可以。StructLayoutAttribute可以。他是Attribute的派生类

        // 摘要:

        //     StructLayoutAttribute类使用户可以控制类或结构的数据字段的物理布局。

        [ComVisible(true)]

        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]

        public sealed class StructLayoutAttribute : Attribute

    从上述定义描述,可以知道StructLayoutAttribute 就是我们想要的类属性,"以控制类或结构的数据字段的物理布局"

    3、DEMO测试:

    第一种:Auto

            [StructLayout(LayoutKind.Auto)]

            class A

            {

                public short a = 0;

                public int b = 0;

                public long c = 0;

            }

                    A a = new A();

                    int asize = Marshal.SizeOf(a.a);//直接引发异常

                    int bsize = Marshal.SizeOf(a.b);

                    int csize = Marshal.SizeOf(a.c);

                    int allsize = Marshal.SizeOf(a);

                    MessageBox.Show(string.Format("a.Size : [{0}], b.Size : [{1}], c.Size : [{2}], totale : [{3}]", asize, bsize, csize, allsize));

    第二种:Explicit

            [StructLayout(LayoutKind.Explicit)]//用到Explicit,必须要对成员的大小或是偏移量,有个精确的设置才成员,汗一下,对每个成员喔,不建议使用这个

            class A

            {

                [FieldOffset(0)]//只能配合布局枚举项为LayoutKind.Explicit时,才可以使用字段偏量设置

                public short a = 0;

                [FieldOffset(2)]

                public int b = 0;

                [FieldOffset(6)]

                public long c = 0;

            }

                    A a = new A();

                    int asize = Marshal.SizeOf(a.a);//如果没有FieldOffset的成员设置,直接引发异常

                    int bsize = Marshal.SizeOf(a.b);

                    int csize = Marshal.SizeOf(a.c);

                    int allsize = Marshal.SizeOf(a);

                    MessageBox.Show(string.Format("a.Size : [{0}], b.Size : [{1}], c.Size : [{2}], totale : [{3}]", asize, bsize, csize, allsize));

    第三种:Sequential

            [StructLayout(LayoutKind.Sequential)]//Sequential有序,可不连续,至于他为啥可以成功,我还想让大牛指点其内部与sizeof配置使用的原理。

            class A

            {

                public short a = 0;

                public int b = 0;

                public long c = 0;

            }

                     A a = new A();

                    int asize = Marshal.SizeOf(a.a);//直接成功

                    int bsize = Marshal.SizeOf(a.b);

                    int csize = Marshal.SizeOf(a.c);

                    int allsize = Marshal.SizeOf(a);

                    MessageBox.Show(string.Format("a.Size : [{0}], b.Size : [{1}], c.Size : [{2}], totale : [{3}]", asize, bsize, csize, allsize));

    如图:

  • 相关阅读:
    今天不谈技术,谈感情~
    外派金融公司
    OAuth2-简介
    Zookeeper实战-分布式锁
    Zookeeper-基础
    Minio-对象存储
    Redis实战-BloomFilter
    Redis实战-详细配置-优雅的使用Redis注解/RedisTemplate
    Redis-基础
    SpringBoot-表单验证-统一异常处理-自定义验证信息源
  • 原文地址:https://www.cnblogs.com/zeroone/p/3306927.html
Copyright © 2011-2022 走看看