用过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. oracle 使用正则表达式获取字符串中包含的数字

    select REGEXP_REPLACE('字符串中包含的数字123,提取后就是123', '[^0-9]', '') from dual;

  2. [leetcode]333. Largest BST Subtree最大二叉搜索树子树

    Given a binary tree, find the largest subtree which is a Binary Search Tree (BST), where largest mea ...

  3. HTML实例

    HTML内容繁多,不易记忆,故将此网址 作为查阅复习的工具http://www.w3school.com.cn/example/html_examples.asp

  4. Django之virtualenv下安装xadmin

    1.安装xadmin,通过pip 进入virtualenv pip安装xadmin pyyuc:~ yuchao$ source PycharmProjects/mxvenv/bin/activate ...

  5. myschool 1204

    http://oj.jxust.edu.cn/problem.php?id=1274 #include <iostream> #include <set> using name ...

  6. Codeforces 595B. Pasha and Phone 容斥

    B. Pasha and Phone time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  7. 2018年上半年UI领域主要的13个设计趋势

    2018年时间过半,通过过去的6个月的观察,其实我们已经可以对于2018年的整个UI领域的设计趋势有了一个更为清晰的判断. 也是推出这篇文章比较合理的时机.下面我们就一起来回顾一下,过去的半年当中,U ...

  8. crontab定时任务操作

    一.查看定时任务 crontab -l 二.添加定时任务 crontab -e (一)执行外部链接 //每隔10分钟执行1次 */ * * * * /usr/bin/curl "http:/ ...

  9. 2018.10.14 bzoj4571: [Scoi2016]美味(主席树)

    传送门 自认为是一道思想很妙的题. 直接分析问题. 如果没有xxx的干扰直接上可持久化01trie01trie01trie走人. 但现在有了xxx这个偏移量. 相当于把整个01trie01trie01 ...

  10. SPSS-两变量相关性分析

    两个变量之间存在确定性:关系和不确定关系(会存在一定的波动范围),就好比你的亲生母亲绝对只有一个,而你的亲叔叔可能有好几个(可以在1叔—4叔之间波动) 相关性一般分为   1:强正相关关系  (一个值 ...