C#由转换二进制所引起的思考,了解下?

【导读】最近遇到很有意思转换二进制的问题,有部分童鞋俨然已了解,可能也有一部分童鞋没碰到过也就不知情,这里我们来深入学习下转换二进制所带来的问题。

在写此篇文章时,非常开心,收到再一次连任MVP的邮件,这是我第4年连任,希望能再接再厉,一如既往能够给大家分享我所获

二进制转换问题

假设现在我们有一个int类型的数据,它的范围区间暂且定在0-15之间,我们需要将其转换为二进制,然后获取二进制中的每一位,若不足4位则0填充。看似很简单是不是,直接通过C#内置APi即可达到此需求,如下:

 var binary = Convert.ToString(7, 2).PadLeft(4, '0').ToArray();

上述将数字7转换为包含二进制位的字符串数组形式,7转换二进制然后不足4位以0填充即(0111),我们如下获取二进制位字符串数组为索引的位,结果应该打印出0,对吗?

var zerobit = binary[0];
Console.WriteLine(zerobit);

好像一点毛病也没有,这是在控制台中进行打印,若是将该数据导出到Excel中,你会发现结果将可能是48或49而不是0或1(你可以一试)这是因为如下:

我们通过调试可知实际上在字符0上还携带有48,这个48实际上是字符0的ASCII码,字符1的ASCII码是49,通过如下代码即可证明:

foreach (var b in System.Text.Encoding.UTF8.GetBytes(binary))
{Console.WriteLine(b.ToString());
}


我们对将对应字符数组索引数据进行如下ToString转换即可避免导出数据时可能出现的问题

var zerobit = binary[0];
Console.WriteLine(zerobit.ToString());

转换字符数组问题

当我们转换为字符数组时,有两种方式,既可采用上述ToArray方法,也可以通过ToCharArray方法来实现,如下,那么哪种方法会更好呢?

var binary = Convert.ToString(7, 2).PadLeft(4, '0').ToArray();var binary1 = Convert.ToString(7, 2).PadLeft(4, '0').ToCharArray();

此时比较此二者方法的性能好坏,只能去看对应源码实现,首先我们来看看ToCharArray方法,如下:

public unsafe char[] ToCharArray()
{if (Length == 0){return Array.Empty<char>();}char[] array = new char[Length];fixed (char* smem = &_firstChar){fixed (char* dmem = &array[0]){wstrcpy(dmem, smem, Length);}}return array;
}
internal unsafe static void wstrcpy(char* dmem, char* smem, int charCount)
{Buffer.Memmove((byte*)dmem, (byte*)smem, (uint)(charCount * 2));
}

上述对于ToCharArray代码量还是不多,我们来看看ToArray方法实现,如下:

public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)
{if (source == null){throw Error.ArgumentNull("source");}return new Buffer<TSource>(source).ToArray();
}

上述只是写了一个扩展方法,我们继续往下看Buffer类的具体实现,如下:

internal Buffer(IEnumerable<TElement> source)
{TElement[] array = null;int num = 0;ICollection<TElement> collection = source as ICollection<TElement>;if (collection != null){num = collection.Count;if (num > 0){array = new TElement[num];collection.CopyTo(array, 0);}}else{foreach (TElement item in source){if (array == null){array = new TElement[4];}else if (array.Length == num){TElement[] array2 = new TElement[checked(num * 2)];Array.Copy(array, 0, array2, 0, num);array = array2;}array[num] = item;num++;}}items = array;count = num;
}

从代码量上看就觉得ToArray方法实现稍微复杂一点,所以我们选择使用ToCharArray会更好,我要是如此草草结束此文,一定会喷。

原归正传,我们一步步来分析,如上做了一点优化,首先会判断参数是否属于集合接口,若是则直接通过复制转换为数组形式,但是我们知道字符串肯定没有实现ICollection<T>接口,所以走另外一个条件分支,但是有的童鞋可能就有疑问了,此时为何可以遍历呢?那是因为针对字符实现了IEnumerable<char>接口,所以可以进行遍历,如下

public sealed class CharEnumerator : IEnumerator, ICloneable, IEnumerator<char>, IDisposable
{......}

接下来则是初始化容量为4的数组,为何这里为4呢?这里我认为应该谈不上优化,与其说是实现者的一种拍脑袋的想法,我倾向于理解为是一种权衡或考量,既然转到此分支说明一定是转换为二进制位的数组,比如上述进行填充后长度刚好为4。再接下来无用我再多讲,就是遍历所有字符数组,将每一个字符串添加到数组中去,直到数组长度和变量值(num)相等最终进行一次性复制,最终将数组赋值给数组元素以及将变量num赋值给数组元素的数量(count)。 

 

好了,讲解了这么多,那么问题来了,到底谁的性能会更好呢?

ToCharArray方法实现底层采用指针操作转化为字符数组,而利用ToArray方法由于string没有实现ICollection<T>接口,也就是说根本不清楚字符串中字符数组的长度,所以只能采取低效遍历的方式去进行转换,我们可认为通过中间缓冲区的方式(即上述通过实例化数组作为桥梁最终进行复制)实现。

由此得出,在将字符串转换为字符数组时,一定要用ToCharArray方法而不是ToArray,ToCharArray性能优于ToArray方法,我不禁在想,针对字符转换为数组只提供ToCharArray方法不就好了么,为何还要提供ToArray方法,让人容易产生误会,它的场景难道还有其他吗?

本文详细讲解了在转换二进制数据所引发的一点个人思考,在将字符串转换为字符数组时,通过方法名称意思可能直接就用ToCharArray方法,但是又偏偏提供了字符串的ToArray方法,其本质是针对字符数组的扩展方法,如果对源码不了解的话,根本就不清楚到底应该用哪一个,从性能角度讲,ToCharArray方法优于ToArray方法,至于最终用哪一个,你说了算。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309003.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.Net Core In Docker 在容器内编译并发布

Docker可以说是现在微服务&#xff0c;DevOps的基础&#xff0c;咱们.Net Core自然也得上Docker。.Net Core发布到Docker容器的教程网上也有不少&#xff0c;但是今天还是想来写一写。你搜.Net core程序发布到Docker网上一般常见的有两种方案&#xff1a;1、在本地编译成Dll文件…

带你深入探究云原生时代的分布式操作系统 Kubernetes

过去几年&#xff0c;以 docker、kubernetes 为代表的容器技术已发展为一项通用技术&#xff0c;BAT、滴滴、京东、头条等大厂&#xff0c;都争相把容器和 k8s 项目作为技术重心&#xff0c;试图“放长线钓大鱼”。就说腾讯吧&#xff0c;目前基本所有业务都跑在云上&#xff0…

C# 9.0 新特性之 Lambda 弃元参数

阅读本文大概需要不到 1 分钟。弃元&#xff08;Discards&#xff09; 是在 C# 7.0 的时候开始支持的&#xff0c;它是一种人为丢弃不使用的临时虚拟变量。语法上它是用来赋值的&#xff0c;但它却不被分配存储空间&#xff0c;即没有值&#xff0c;所以不能从中读取值。弃元用…

应用交付老兵眼中的Envoy, 云原生时代下的思考

Envoy 是云原生时代的明星&#xff0c;其本质是反向代理负载均衡类软件&#xff0c;领域上归于应用交付&#xff0c;那么作为应用交付领域的老兵如何看待 Envoy&#xff0c;Envoy 又引发了哪些关于传统应用交付领域的思考&#xff1f;关于作者林静&#xff0c;F5 软件方向解决方…

asp.net core程序在k8s中基于rabbitmq队列消息数的HPA实践!

背景最近一段时间&#xff0c;陆陆续续的把手里头项目都迁移到了k8s中&#xff0c;期间遇到很多的坑&#xff0c;并且也学到了许多k8s的知识&#xff08;从0-1&#xff09;&#xff0c;大家都知道k8s中的一大特性是自动扩容&#xff0c;对此结合自己的业务发现很是有“用武之地…

如何优雅做系统错误提示?

这里是Z哥的个人公众号每周五11&#xff1a;45 按时送达当然了&#xff0c;也会时不时加个餐&#xff5e;我的第「149」篇原创敬上大家好&#xff0c;我是Z哥。不管是日常的工作中还是生活中&#xff0c;我们每天会用到很多软件系统。不知道你有没有过这样的感受&#xff0c;当…

搭建一套ASP.NET Core+Nacos+Spring Cloud Gateway项目

前言伴随着随着微服务概念的不断盛行&#xff0c;与之对应的各种解决方案也层出不穷。这毕竟是一个信息大爆发的时代&#xff0c;各种编程语言大行其道&#xff0c;各有各的优势。但是有一点未曾改变&#xff0c;那就是他们服务的方式&#xff0c;工作的时候各司其职&#xff0…

如何在ASP.NET Core中集成ElasticSearch

本文来自&#xff1a;https://www.blexin.com/en-US/Article/Blog/How-to-integrate-ElasticSearch-in-ASPNET-Core-70图片我敢打赌&#xff0c;您肯定会被要求向Web应用程序中添加高级搜索功能&#xff0c;而且通常是全文的类似Google的搜索。在技术电子商务的开发过程中&…

了解下C#由转换二进制所引起的思考

【导读】最近遇到很有意思转换二进制的问题&#xff0c;有部分童鞋俨然已了解&#xff0c;可能也有一部分童鞋没碰到过也就不知情&#xff0c;这里我们来深入学习下转换二进制所带来的问题。在写此篇文章时&#xff0c;非常开心&#xff0c;收到再一次连任MVP的邮件&#xff0c…

如何利用.NETCore向Azure EventHubs准实时批量发送数据?

最近在做一个基于Azure云的物联网分析项目&#xff1a;.netcore采集程序向Azure事件中心(EventHubs)发送数据&#xff0c;通过Azure EventHubs Capture转储到Azure BlogStorage&#xff0c;供数据科学团队分析。为什么使用Azure事件中心&#xff1f;Azure事件中心是一种Azure上…

C++实现二叉树

代码如下: #include<iostream> #include <queue> #include <stack> using namespace std;class BinTree { private:class TreeNode{public:int data;TreeNode *left;TreeNode *right;TreeNode ():data(0),left(nullptr),right(nullptr){}TreeNode(int e):da…

MySql :Could not create connection to database server.

错误&#xff1a; Exception in thread “main” org.apache.ibatis.exceptions.PersistenceException:Error querying database. Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. The error …

Vue 3拖更,尤雨溪介绍最新进展

Vue.js 作者尤雨溪近日介绍了 Vue 3 的最新进展。尤雨溪表示&#xff0c;由于在 Vue 3 上花费的大部分时间都投入到了设计和构建稳定的内核上&#xff0c;不过要让整个框架处于"ready"状态&#xff0c;不仅仅是内核的问题&#xff0c;还需要有兼容版本的支持库 &…

Mysql@和@@符号的详细使用说明

一、概述 是用户变量&#xff0c;是系统变量。 二、使用语法及实践 用户自定义变量 1、用户定义变量语法 SET var_name expr [, var_name expr] 如&#xff1a;set t1 100; 2、获取用户定义变量值方式&#xff0c;如&#xff1a; select t1 from dual; 如下图 系统变…

探讨NET Core数据进行3DES加密或解密弱密钥问题

【导读】之前写过一篇《探讨.NET Core数据进行3DES加密和解密问题》&#xff0c;最近看到有人提出弱密钥问题&#xff0c;换个强密钥不就完了吗&#xff0c;猜测可能是与第三方对接导致很无奈不能更换密钥&#xff0c;所以产生本文解决.NET Core中3DES弱密钥问题&#xff0c;写…

C++实现表达式树

代码如下: #include <iostream> #include <string> #include <stack> #include <queue> using namespace std;class Tree { private:class Node{public:char val;Node * left;Node *right;Node(char val):val(val),left(nullptr),right(nullptr){}Nod…

redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作

前段时间在做用户画像的时候&#xff0c;遇到了这样的一个问题&#xff0c;记录某一个商品的用户购买群&#xff0c;刚好这种需求就可以用到Redis中的Set&#xff0c;key作为productID&#xff0c;value就是具体的customerid集合&#xff0c;后续的话&#xff0c;我就可以通过p…

IDEA如何在包下建立子包

idea如何在包下建立子包 第一次在包下建立子包时候出现了问题 在java > springmvc包下再new上一个package controller的时候就会出现这个样子 如何解决 在IDEA2019 中的Show Options Menu下有一个Compacket Middle Packages将它关闭即可 解决成功

.NET Core微服务开发选项

微服务开发的关注点有哪些&#xff1f;微服务构最终的目标是实现业务的价值&#xff0c;交付&#xff0c;为了让开发人员更加关注业务开发和交付&#xff0c;微服务需要一些比较底层的基础设置&#xff0c;我们也称为微服务公共关注点。配置管理&#xff1a;对微服务可变参数进…