背景

最近在群里,有人问如何深度比较2个对象相等,感觉很有意思,就自己研究了一下,并写了一个开源的小类库,地址如下https://github.com/lamondlu/ObjectEquality。

如果想直接使用这个类库,可以使用Nuget进行安装

Install-Package ObjectEquality

对象比较有几种情况

  1. 对象是值类型或者String,这里仅需要判断值是否相等
  2. 对象是Struct,需要判断Struct的每个字段是否一致
  3. 对象是集合,需要判断对应位置的对象是否相等
  4. 对象是数组,需要判断对应位置的对象是否相等
  5. 对象是Class, 需要判断Class的每个字段是否一致

这里可能有缺漏,大家可以帮我补充。

编写代码

这里我首先创建了一个IEquality接口,在其中定义了一个IsEqual方法,这个方法就是判断2个对象是否一致的方法。后面我会针对上面说明的几种对比场景,分别创建对应的实现类。

    public interface IEquality{Func<object, bool> MatchCondition { get; }bool IsEqual(object source, object target);}

这里MatchCondition是一个委托,它定义了当前对比类的匹配条件。

第二步,我们针对上述的几种对比场景,创建对应的实现类

值类型相等判断实现类

    internal class ValueTypeEquality : IEquality{public Func<object, bool> MatchCondition{get{return p => p.GetType().IsValueType || p.GetType() == typeof(string);}}public bool IsEqual(object source, object target){return source.Equals(target);}}

值类型的判断比较简单,直接调用Object类的Equals方法即可。

String类型虽然不是值类型,但是这里我们需要把它归到值类型中。

Struct相等判断实现类

    internal class StructEquality : IEquality{public Func<object, bool> MatchCondition{get{return p => p.GetType().IsValueType && !p.GetType().IsPrimitive && !p.GetType().IsEnum;}}public bool IsEqual(object source, object target){var type = source.GetType();foreach (var prop in type.GetProperties()){var equality = EqualityCollection.Equalities.First(p => p.MatchCondition(prop.GetValue(source)));var result = equality.IsEqual(prop.GetValue(source),prop.GetValue(target));if (!result){return false;}}return true;}}   

这里我们读取了Struct中的每个属性,分别进行判断,如果有一个判断失败,即认为2个Struct对象不相等。

这里EqualityCollection是判断器集合,后续会添加这个类的代码。

集合相等判断实现类

    internal class GenericCollectionEquality : IEquality{public Func<object, bool> MatchCondition{get{return p => p.GetType().IsGenericType;}}public bool IsEqual(object source, object target){var type = source.GetType();var genericType = type.GetGenericArguments()[0];var genericCollectionType = typeof(IEnumerable<>).MakeGenericType(genericType);if (type.GetInterfaces().Any(p => p == genericCollectionType)){var countMethod = type.GetMethod("get_Count");var sourceCount = (int)countMethod.Invoke(source, null);var targetCount = (int)countMethod.Invoke(target, null);if (sourceCount != targetCount){return false;}var sourceCollection = (source as IEnumerable<object>).ToList();var targetCollection = (target as IEnumerable<object>).ToList();for (var i = 0; i < sourceCount; i++){var equality = EqualityCollection.Equalities.First(p => p.MatchCondition(sourceCollection[i]));var result = equality.IsEqual(sourceCollection[i], targetCollection[i]);if (!result){return false;}}}return true;}}

这里我们首先判断了集合的元素的数量是否一致,如果不一致,即这2个集合不相等。如果一致,我们继续判断对应位置的每个元素是否一致,如果全部都一直,则2个集合相当,否则2个集合不相等。

数组相等判断实现类

    internal class ArrayEquality : IEquality{public Func<object, bool> MatchCondition{get{return p => p.GetType().IsArray;}}public bool IsEqual(object source, object target){Array s = source as Array;Array t = target as Array;if (s.Length != t.Length){return false;}for (var i = 0; i < s.Length; i++){var equality = EqualityCollection.Equalities.First(p => p.MatchCondition(s.GetValue(i)));var result = equality.IsEqual(s.GetValue(i), t.GetValue(i));if (!result){return false;}}return true;}}

数组相等的判断类似集合,我们首先判断数组的长度是否一致,然后判断对应位置的元素是否一致。

类判断相等实现类

    internal class ClassEquality : IEquality{public Func<object, bool> MatchCondition{get{return p => p.GetType().IsClass;}}public bool IsEqual(object source, object target){var type = source.GetType();foreach (var prop in type.GetProperties()){var equality = EqualityCollection.Equalities.First(p => p.MatchCondition(prop.GetValue(source)));var result = equality.IsEqual(prop.GetValue(source), prop.GetValue(target));if (!result){return false;}}return true;}}

添加判断相等实现类集合

    public static class EqualityCollection{public static readonly List<IEquality> Equalities = new List<IEquality> {new StructEquality(),new ValueTypeEquality(),new ArrayEquality(),new GenericCollectionEquality(),new ClassEquality()};}

这里我们定义了一个静态类,来存储程序中使用的所有判断器。

这里在判断器集合中,实现类的其实是有顺序的,StructEquality必须要放到ValueTypeEquality的前面,因为Struct也是值类型,如果不放到最前面,会导致判断失败。

创建判断器入口类

    public class ObjectEquality{public bool IsEqual(object source, object target){if (source.GetType() != target.GetType()){return false;}if (source == null && target == null){return true;}else if (source == null && target != null){return false;}else if (source != null && target == null){return false;}var equality = EqualityCollection.Equalities.First(p => p.MatchCondition(source));return equality.IsEqual(source, target);}}

前面所有实现类的访问级别都是Internal, 所以我们需要创建一个判断器入口类, 外部只能通过ObjectEquality类的实例来实现判断相等。

最终效果

下面我列举几个测试用例,看看效果是不是我们想要的

对比Struct

    public struct DemoStruct{public int Id { get; set; }public string Name { get; set; }}
    var a = new DemoStruct();a.Id = 1;a.Name = "Test";var b = new DemoStruct();b.Id = 1;b.Name = "Test";var c = new DemoStruct();b.Id = 2;b.Name = "Test";ObjectEquality objectEquality = new ObjectEquality();objectEquality.IsEqual(a,b); //trueobjectEquality.IsEqual(a,c); //false

对比类

    public class SimpleClass{public int Id { get; set; }public string Name { get; set; }}
    var a = new SimpleClass{Id = 1,Name = "A"};var b = new SimpleClass{Id = 1,Name = "A"};var c = new SimpleClass{Id = 2,Name = "A"};ObjectEquality objectEquality = new ObjectEquality();objectEquality.IsEqual(a,b); //trueobjectEquality.IsEqual(a,c); //false

对比数组

    var a = new int[] { 1, 2, 3 };var b = new int[] { 1, 2, 3 };var c = new int[] { 1, 1, 2 }; ObjectEquality objectEquality = new ObjectEquality();objectEquality.IsEqual(a,b); //trueobjectEquality.IsEqual(a,c); //false

转载于:https://www.cnblogs.com/lwqlun/p/10159770.html

.NET中如何深度判断2个对象相等相关推荐

  1. python中的is判断引用的对象是否一致,==判断值是否相等

    python中的is判断引用的对象是否一致,==判断值是否相等 a = 10 b = 20 list = [1,2,3,4,5] print(a in list) print(b not in lis ...

  2. js判断数组,对象,是否为空,是否含有某个值,判断数组中对象是否有某个值

    一.数组 1.判断数组是否为空                  arr.length let arr = []; if (arr.length == 0){console.log("数组为 ...

  3. js中判断两个对象是否相等。

    js中判断两个对象是否相等. js中的Object.Array.Function等复杂数据类型,是无法直接用==和===操作符进行比对的. Object对比 const tar = { name:'张 ...

  4. JS中判断对象是对象还是数组

    JS中判断对象是对象还是数组的方法 JS中判断对象是不是数组的方法 JavaScript中检测对象的方法  1.typeof操作符  这种方法对于一些常用的类型来说那算是毫无压力,比如Function ...

  5. 前端 项目中 判断两个对象value值是否相等

    项目中的实例 看上图知道,点击了支付时,验证了选中行的主体信息,不一致就给提示信息,一致就出现弹框(这里弹框没有写) 那么我们就要在循环遍历的基础上,判断选中的行信息的 某个值是否相等. 也就是 判断 ...

  6. vue 对象判断为空_Vue中可用的判断对象是否为空的方法

    vue有两个方法可用 1. JSON.stringify(evtValue)=='{}' 2. Object.keys(xxx).length==0 js判断对象是否为空对象的几种方法 1.将json ...

  7. containskey java_Java Map.containsKey()方法:判断Map集合对象中是否包含指定的键名

    搜索热词 Java 集合类中的 Map.containsKey() 方法判断 Map 集合对象中是否包含指定的键名.如果 Map 集合中包含指定的键名,则返回 true,否则返回 false. 语法: ...

  8. 自动驾驶感知中的深度学习

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 自动驾驶是一种自主决策系统,它处理来自不同车载来源的观测流,如照相 ...

  9. 读书人:人机融合中的深度态势感知

    雅典学院(拉斐尔) 来源:人机与认知实验室 "你现在的气质里,藏着你走过的路,读过的书和爱过的人." - 电影<卡萨布兰卡>里的一句话 <追问人工智能>-- ...

最新文章

  1. 初学Python——文件操作第二篇
  2. HTML5系列四(特征检测、Modernizr.js的相关介绍)
  3. 十九、前端必学Bootstrap美化(下篇)
  4. Linux查看负载相关命令
  5. PHP 中 empty is_null 和 isset 的测试
  6. Java Recruitment(1)
  7. MicroProfile变成了Eclipse MicroProfile
  8. three.js 后期处理,物体高亮
  9. 3星|《大产品,小团队》:携程软件开发流程改进的故事
  10. LeetCode 407. Trapping Rain Water II
  11. Linux学习笔记(一):Linux介绍
  12. List集合排序总结
  13. kafka系列之kafka分区与备份(4)
  14. PDF可以修改吗,如何在PDF上修改文字
  15. glassfish 配置 mysql_GlassFish MySql连接池配置 | 学步园
  16. 根据经纬度查询地名,
  17. 嵌入式学习硬件篇------初识ARM
  18. 怎么在线免费压缩图片
  19. linux系统视频软件,腾讯视频Linux版下载
  20. 谷歌三篇重要论文读后感

热门文章

  1. 牛逼了 这 7 个 Python 入门实战项目,我打 99.99 分
  2. java中decrement,Java Math decrementExact()用法及代码示例
  3. ICCV 2021 揭榜!十大方向抢先看!(Transformer/分割/Action/插帧/超分等)
  4. 计算机视觉论文-2021-06-29
  5. CVPR 2021 | 姿态可控的语音驱动
  6. AMD宣布350亿美元收购赛灵思,CPU、GPU、FPGA全凑齐
  7. 还在修改博士论文?这份《博士论文写作技巧》为你指南
  8. 大数据分析必须要会的数据预处理操作(二)!!!
  9. windows 安装tensorflow
  10. 地理坐标系和投影坐标系的区别