上午,有位初学者朋友问:如何比较两个字节数组中各字节是否相等?

不许笑,我一向反对嘲笑初学者,初学者不认真学习时你可以批评,但不能讥嘲。你不妨想想,你自己开始学习编程的时候又是什么个光景?

好,于是,这位初学者朋友就做了以下尝试:

            byte[] buffer1 = { 0x001, 0x002, 0x003 };
byte[] buffer2 = { 0x001, 0x002, 0x003 };
Console.WriteLine(buffer1 == buffer2);

想一下,这个方法行吗?结果一运行,这位朋友差点晕倒,呵呵。buffer1 == buffer2比较的是这两个byte[]实例,不会去比较里面的元素。

这位朋友吸取教训后,把代码作如下修改:

            byte[] buffer1 = { 0x001, 0x002, 0x003 };
byte[] buffer2 = { 0x001, 0x002, 0x003 };
bool isEq = false;
if (buffer1.Length != buffer2.Length)
{
isEq = false;
}
else
{
isEq = true;
for (int i = ; i < buffer1.Length; i++)
{
if (buffer1[i] != buffer2[i])
{
isEq = false;
break;
}
}
}
Console.WriteLine(isEq);

这一次有效果了,来,为这位朋友所取得的成就鼓掌。

到了此处,大概是可以了结了,可是这位朋友很执着,他继续问:“有没有更简单一些的方法?”

我不回答,于是,他又动起脑子,不久,又写出一段代码:

    public static class ByteArrayExt
{
public static bool IsEqual(this byte[] src, byte[] dis)
{
bool isEq = false;
if (src.Length != dis.Length)
{
isEq = false;
}
else
{
isEq = true;
for (int i = ; i < src.Length; i++)
{
if (src[i] != dis[i])
{
isEq = false;
break;
}
}
}
return isEq;
}
}

他把刚才的代码就写到扩展方法中,扩展对象是byte[]类型。以后只要遇到这种情况就不必每次都写那么多代码,直接调用扩展方法就可以了。

            Console.WriteLine(buffer1.IsEqual(buffer2));

不错,看来这位同学悟性挺高,懂得发挥扩展方法的作用了。但是,这位兄台仍旧不满意,还不够简单。

其实,.NET类库已经有一个现成的方法了,也是扩展方法,要比较两个序列(如数组,列表等)中各个元素是否相等,只要调用该方法即可,不用自己写代码实现。什么方法呢?这个方法的芳名叫做SequenceEqual。

因此,整个程序的代码我们完全可以很简单地完成。

            byte[] buffer1 = { 0x001, 0x002, 0x003 };
byte[] buffer2 = { 0x001, 0x002, 0x003 };
Console.WriteLine(buffer1.SequenceEqual(buffer2));

这位仁兄如获至宝,马上兴奋起来,啊!原来还可以这样耍!就好比孙行者在龙宫发现如意棍一样的兴奋。

可能有些朋友又会问了,如果我们比较的元素是自己编写的类呢?我需要自己的比较规则。无妨,SequenceEqual方法还有一个重载,就是可以向方法的参数传一个实现了IEqualityComparer<in T>接口的对象。

由于EqualityComparer<T>类实现了该接口,在我自自定义比较器时,可以直接从该类派生。

比如我们定义了一个“帅哥”类,它包含Name和ID两个属性,对于任意两个“帅哥”对象,只要ID相等,我们就认为他们是同一位帅哥。

    public class 帅哥
{
public int ID { get; set; }
public string Name { get; set; }
}

然后,我们定义一个比较器,专门用于判断两位帅哥是否为同一位帅哥。

    public class 帅哥EqualityComparer : EqualityComparer<帅哥>
{
public override bool Equals(帅哥 x, 帅哥 y)
{
if (x.ID == y.ID)
{
return true;
}
return false;
} public override int GetHashCode(帅哥 obj)
{
return obj.ID.GetHashCode();
}
}

来,开始做测试吧。

            帅哥[] sgarr1 =
{
new 帅哥 { ID = , Name = "小李" },
new 帅哥 { ID = , Name = "小刘" },
new 帅哥 { ID = , Name = "小王" }
};
帅哥[] sgarr2 =
{
new 帅哥 { ID = , Name = "小李" },
new 帅哥 { ID = , Name = "小刘" },
new 帅哥 { ID = , Name = "小王" }
};
帅哥[] sgarr3 =
{
new 帅哥 { ID = , Name = "小张" },
new 帅哥 { ID = , Name = "小黄" },
new 帅哥 { ID = , Name = "小胡" }
}; // 实例化比较器
帅哥EqualityComparer comparer = new 帅哥EqualityComparer(); Console.WriteLine(sgarr1.SequenceEqual(sgarr2, comparer));
Console.WriteLine(sgarr2.SequenceEqual(sgarr3, comparer));

至此,相信这位仁兄已经不亦乐乎了。

总结:我们平时做项目写程序都应该向这位仁兄学习,努力寻找最简单最高效的方法去处理问题。

【.net】从比较两个字节数组谈起的更多相关文章

  1. 在 Perl看来, 字符串只有两种形式. 一种是octets, 即8位序列, 也就是我们通常说的字节数组. 另一种utf8编码的字符串, perl管它叫string. 也就是说: Perl只熟悉两种编

    在 Perl看来, 字符串只有两种形式. 一种是octets, 即8位序列, 也就是我们通常说的字节数组. 另一种utf8编码的字符串, perl管它叫string. 也就是说: Perl只熟悉两种编 ...

  2. (IEEE-754) 字节数组与浮点数之间的互相转换(MODBUS float类型)

    在做上位机开发过程中,经常会碰到字节数组与浮点数,整数等数据之间的转换,有时为了验证数据是否解析正确,得借助于IEEE浮点数工具,本文把基于c#实现的浮点数与字节数组(或16进制的字符串)转换的实现方 ...

  3. C#字节数组转换成字符串

    C#字节数组转换成字符串 如果还想从 System.String 类中找到方法进行字符串和字节数组之间的转换,恐怕你会失望了.为了进行这样的转换,我们不得不借助另一个类:System.Text.Enc ...

  4. C# 16进制与字符串、字节数组之间的转换(转)

    1.请问c#中如何将十进制数的字符串转化成十六进制数的字符串   //十进制转二进制 Console.WriteLine("十进制166的二进制表示: "+Convert.ToSt ...

  5. Java:IO流其他类(字节数组流、字符数组流、数据流、打印流、Properities、对象流、管道流、随机访问、序列流、字符串读写流)

    一.字节数组流: 类 ByteArrayInputStream:在构造函数的时候,需要接受数据源,而且数据源是一个字节数组. 包含一个内部缓冲区,该缓冲区包含从流中读取的字节.内部计数器跟踪 read ...

  6. Java之ByteArrayInputStream和ByteArrayOutputStream-操作字节数组的类

    ByteArrayInputStream和ByteArrayOutputStream 源:内存中的字节数组 目的:内存中的字节数组 这两个流对象不涉及底层资源的调用,操作的都是内存中的数组,所以不需要 ...

  7. Java中二进制、十进制、十六进制及ASCII码与String及字节数组与十六进制之间的转换

    public class DigitalTrans { /** * 数字字符串转ASCII码字符串 * * @param String * 字符串 * @return ASCII字符串 */ publ ...

  8. C语言字节数组转换为基本数据类型

    首先,必须明确基本类型在不同环境下字节的大小 这里用到了unsigned char:1  int:4  double:8 自己主要想用的是将字节数组转换为int型,double型 具体来说,将接收到的 ...

  9. java对获取的字节数组进行处理

    java对获取的字节数组bytes[]进行处理: 第一种,直接将该字节数组转换为字符串(部分): String content = ,); //从位置0开始获取2个字节 这样,对获取的数据报进行全部转 ...

随机推荐

  1. Windows Phone 8.1 新特性 - 控件之列表选择控件

    本篇我们来介绍Windows Phone 8.1 新特性中的列表选择控件. 在Windows Phone 8 时代,大家都会使用 LongListSelector 来实现列表选择控件,对数据进行分组显 ...

  2. 链表反转 (Multi-method)

    链表反转是链表相关问题最基础的知识,做完LeetCode中LinkedList后才会有这种体会,因为ACM算法中不会涉及这一部分.解决这一问题有多种方法,在面试中面试官通常也会要求写出多种.包括sta ...

  3. PL/SQL通过存储过程为相同数据添加序号

    在Oracle数据库中存有一串数据(Ori_Seq),数据包含不等量重复: 为方便查看与管理,现希望添加一字段(New_Seq),在原有数据的末尾为其添加一串序号,相同数据序号从小到大排列,序号长度为 ...

  4. js中的变量小例子

    s中的变量function foo(){ n=99;}alert(n);//undefined,因为没有调用该函数 function foo(){ n=99;}foo();alert(n);//99, ...

  5. 套题 codeforces 361

    A题((Mike and Cellphone) 看起来好像需要模拟数字键位的运动,可是,只要判断出那些必然YES的数字组合不就好了么 #include <cstdio> #include ...

  6. FastCgi 与 PHP-FPM

    - 如果现在请求的是 /index.php,根据配置文件,nginx 知道这个不.是静态文件,需要去找 PHP 解析器来处理,那么他会把这个请求简单处理后交给 PHP 解析器.Nginx 会传哪些数据 ...

  7. 【转】【Linux】 临界区,互斥量,信号量,事件的区别

    原文地址:http://blog.itpub.net/10697500/viewspace-612045/ Linux中 四种进程或线程同步互斥的控制方法1.临界区:通过对多线程的串行化来访问公共资源 ...

  8. Tomcat相关的笔记

    本文只是记录一下tomcat运维用到过的知识,都是网络上收集来的资料,侵删 JVM的内存 内存分配 -XX:PermSize尽量比-XX:MaxPermSize小,-XX:MaxPermSize> ...

  9. C# Entity Framework查询小技巧 NoTracking

    在使用Entity Framework做查询的时候,如果只需要显示,而不用保存实体,那么可以用AsNoTracking()来获取数据. 这样可以提高查询的性能. 代码如下: var context = ...

  10. Java多线程20:多线程下的其他组件之CountDownLatch、Semaphore、Exchanger

    前言 在多线程环境下,JDK给开发者提供了许多的组件供用户使用(主要在java.util.concurrent下),使得用户不需要再去关心在具体场景下要如何写出同时兼顾线程安全性与高效率的代码.之前讲 ...