用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便。
那C#为什么没有这个关键字呢?怎么实现这个功能?其实C#只是没有了这个关键字,但是功能是能实现的,而且也是非常方便,并且是安全的。
网上有人用StructLayout特性来实现union,也确实是实现了一些功能。
比如:
C/C++:
    union {
        unsigned char ch
        short ;
        int i;
    };
C#:
    [StructLayout(LayoutKind.Explicit)]
    public struct Class1
    {
        [FieldOffset(0)]
        public byte b;

[FieldOffset(0)]
        public short s;

[FieldOffset(0)]
        public int i;
    }
就可以实现。
但是我要是写个:
    union {
        unsigned char ch[4];
        int i;
        float f;
    } temp;
硬是用C#没有模拟出来,估计我还没有找着合适的方法。因为我写
    [StructLayout(LayoutKind.Explicit)]
    public struct Class1
    {
        [FieldOffset(0)]
        public byte[4] b;

[FieldOffset(0)]
        public short s;

[FieldOffset(0)]
        public int i;
    }
这玩意是编译不通过的。然后折腾了半天,没有折腾出来。后来又回到C/C++想了一番,似乎有些认识。
C/C++用union其实就是使用同一块内存存储不同类型的数据,说白了,就是一块公用的内存,你用啥读取出来就是啥内容。其实计算机中的内存本身也就是这样,你定义一个int i;然后计算机会在内存栈上开辟一块空间,并且这块内存指明了是int类型,但是我们经常看到(int)data,(int*)pt等操作,说明可以强制转换。强制转换不是说把这几块内存的值改变了,只是临时改变了读取方式,然后用这种方式读取这块内存。那这样说来是不是也可以不用union来实现char数组与其他类型之间的转换,答案是必须可以。
比如:
    unsigned char chArr[4] = "";
    float f1 = 45.56f;
    memcpy(chArr, &f1, sizeof(float));
    // 运行结果:113    61    54    66
    printf("%d\t%d\t%d\t%d\n", chArr[0], chArr[1], chArr[2], chArr[3]);
    
    float f2 = 0.00f;
    memcpy(&f2, chArr, sizeof(float));
    printf("%0.2f\n", f2);
    
    float f3 = *(float *)chArr;
    printf("%0.2f\n", f3);

char *pch = (char *)&f3;
    // 运行结果:113    61        54        66
    printf("%d\t%d\t%d\t%d\n", pch[0], pch[1], pch[2], pch[3]);

那好问题来了,C#怎么实现?
那好,答案也来了。当然是用BitConvert。
比如:
    float f = 45.56f;
    byte[] b = BitConverter.GetBytes(f);
    Console.WriteLine("bArr\t: {0}\t{1}\t{2}\t{3}", b[0], b[1], b[2], b[3]);

float f2 = BitConverter.ToSingle(b, 0);
    Console.WriteLine("f2\t: {0}", f2);
完全木有问题啊,而且还安全。

最后呢,咱们看看微软是怎么给咱实现的。

// Converts a float into an array of bytes with length
    // four.
    [System.Security.SecuritySafeCritical]  // auto-generated
    public unsafe static byte[] GetBytes(float value)
    {
        Contract.Ensures(Contract.Result<byte[]>() != null);
        Contract.Ensures(Contract.Result<byte[]>().Length == 4);

return GetBytes(*(int*)&value);
    }

...
    // Converts an int into an array of bytes with length
    // four.
    [System.Security.SecuritySafeCritical]  // auto-generated
    public unsafe static byte[] GetBytes(int value)
    {
        Contract.Ensures(Contract.Result<byte[]>() != null);
        Contract.Ensures(Contract.Result<byte[]>().Length == 4);

byte[] bytes = new byte[4];
        fixed(byte* b = bytes)
            *((int*)b) = value;
        return bytes;
    }

看见了吗?是不是跟上面的C/C++代码很像。其实就是C/C++代码。如果你看不到这段代码,也许你还真不知道,原来以前自己的C/C++代码被搬到了这里。但是微软的公司的代码可不是我写的C/C++那么简单的转换,微软程序员是做了安全检查的。你如果将3个byte的数组转换到float,那对不起,玩不了,你得补一个字节。

好了,给大家附上微软C#开源的源代码地址:
https://referencesource.microsoft.com/#mscorlib/system/bitconverter.cs,9108fa2d0b37805b

C#不用union,而是有更好的方式实现的更多相关文章

  1. C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路

    C#不用union,而是有更好的方式实现   用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...

  2. 代码规范(RL-TOC)用更合理的方式写 JavaScript

    代码可以改变世界 不规范代码可以毁掉世界 只有先学会写规范的代码,才可以走的更远 编程语言之间有很多编程规范都是通用: 命名 不要用语言不明的缩写,不用担心名字过长,名字一定要让别人知道确切的意思; ...

  3. 【译】更快的方式实现PHP数组去重

    原文:Faster Alternative to PHP’s Array Unique Function 概述 使用PHP的array_unique()函数允许你传递一个数组,然后移除重复的值,返回一 ...

  4. [C#] 用一种更优美的方式来替换掉又多又长的switch-case代码段

    switch-case语句是我们编码过程中常用的一种分支语句.然而正所谓成也萧何败萧何,每当我们向一个已经拥有了成百上千行的switch-case代码段中添加新的case分支的时候,我们是否有过为代码 ...

  5. 更快的方式实现PHP数组去重(转)

    概述 使用PHP的array_unique()函数允许你传递一个数组,然后移除重复的值,返回一个拥有唯一值的数组.这个函数大多数情况下都能工作得很好.但是,如果你尝试在一个大的数组里使用array_u ...

  6. 更快的方式实现 PHP 数组去重

    概述 使用PHP的array_unique()函数允许你传递一个数组,然后移除重复的值,返回一个拥有唯一值的数组.这个函数大多数情况下都能工作得很好.但是,如果你尝试在一个大的数组里使用array_u ...

  7. 不用 Notepad++,还有更牛逼的选择!

    来源:oschina.net/news/110987/no-notepad-plus-plus 这两天 Notepad++ 牛逼了,然后引发了大家的关注,具体事件内容请大家自行百度,其实作为文本编辑工 ...

  8. 少年,是时候换种更优雅的方式部署你的php代码了

    让我们来回忆下上次你是怎么发布你的代码的: 1. 先把线上的代码用ftp备份下来 2. 上传修改了的文件 3. 测试一下功能是否正常 4. 网站500了,赶紧用备份替换回去 5. 替换错了/替换漏了 ...

  9. [改善Java代码]集合运算时使用更优雅的方式

    在初中代数中,我们经常会求两个集合的并集.交集.差集等,在Java中也存在着此 类运算,那如何实现呢? 一提到此类集合操作,大部分的实现者都会说:对两个集合进行遍历,即可求出结果.是的,遍历可以实现并 ...

随机推荐

  1. hdoj1251-统计难题 【字典树】

    http://acm.hdu.edu.cn/showproblem.php?pid=1251 统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory ...

  2. Excel Sheet Column Title (STRING - TYPE CONVERTION)

    QUESTION Given a positive integer, return its corresponding column title as appear in an Excel sheet ...

  3. TZOJ 4746 Xiangqi(模拟棋盘数组)

    描述 Xiangqi is one of the most popular two-player board games in China. The game represents a battle ...

  4. iOS 多页面跳转同一页面时数据处理

    如果 同一个界面, 会有10个数据源传进来, 此时 创建 一个总模型fullmodel 存储 10个model 数据, 创建 10个一样的cell, 在 不同数据, 用不同cell处理最好, 千万别于 ...

  5. [leetcode]277. Find the Celebrity谁是名人

    Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...

  6. 零基础学习hadoop到上手工作线路指导(中级篇)

    此篇是在零基础学习hadoop到上手工作线路指导(初级篇)的基础,一个继续总结. 五一假期:在写点内容,也算是总结.上面我们会了基本的编程,我们需要对hadoop有一个更深的理解: hadoop分为h ...

  7. geoserver 的缓存技术

    geoserver提到的缓存工具共有两个:tilecache和geowebcache.geowebcache是java写的,整合进geoserer中. tilecache则是python写的一个小程序 ...

  8. asp.net core 2.1 增加Nlog日志到sql server数据库

    一.增加引用 <PackageReference Include="NLog.Extensions.Logging" Version="1.2.1" /& ...

  9. 2018.09.01 hdu4405 Aeroplane chess (期望dp)

    传送门 期望dp简单题啊. 不过感觉题意不太对. 手过了一遍样例发现如果有捷径必须走. 这样的话就简单了啊. 设f[i]" role="presentation" sty ...

  10. 笔记本的Windows系统怎么设置有了外接鼠标后停用触摸板

    点击控制面板,切换小图标模式,找到鼠标,点击它,然后会弹出一个窗口,找到ELAN选项卡(一般有个红色图标,不过可能需要对应驱动才会有此选项卡),选中插入外置 USB 指向装置时禁用.点击确定保存配置即 ...