DOTNET笔记_值比较的实现
2015-09-20 11:46
232 查看
背景回顾1 在DOTNet的世界中,只有值类型和引用类型两种值类型有以下几种:系统内置的基本值类型,struct,用户自定义的struct类型,Enum类型引用类型:class,string,array,delegate,box-result2 值类型由于直接存储了内容,值类型变量的比较直接,简单;引用类型变量,由于变量本身存储的只是托管堆上的引用,引用变量的直接 == 只是引用的比较,其实这个也挺容易的,但是往往意义不大:如果是经过独自创建的同一类型实例,这种比较肯定不想等;如果只是引用赋值,那么它们肯定相等。还有一种情形,希望通过托管堆上的内容进行进行比较,从而确定这两个对象是否一致。说到引用类型变量的比较,有下面这些方法1)object上定义的静态方法 ReferrenceEquals explicitly比较引用的2)object.Equals(object obj)这个方法的行为往往需要参考具体子类的实现,它相应的影响了 == 的行为。另外,改写了这个方法,相应的GetHashCode方法也需要explicitly改写,成对出现!!3 针对Array,tuple这种数据结构由于本身explicitly实现了IStructuralEquatable接口,因此,在遇到这两种数据结构需要进行基于内容比较的情况,可以将引用转换为IStructuralEquatable,从而调用其Equals方法。针对array,只要确保实现了IEquatable方法或者,通过继承自Object的Equals(Object obj)可以正常的进行值比较就可以正常进行基于内容比较了。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace StructCompareOnArrayAndTuple { class CustomPerson//: //IEquatable<CustomPerson> { public Int32 ID {get; set;} public String Name {get; set;} public UInt16 Age {get; set;} public override bool Equals(object obj) { if (obj == null) { return base.Equals(obj); } return Equals(obj as CustomPerson); //return base.Equals(obj); } public override int GetHashCode() { return ID.GetHashCode(); } private bool Equals(CustomPerson other) { if (other == null) { return base.Equals(other); } return (other.Age == this.Age) && (other.ID == this.ID) && (other.Name.Equals(this.Name, StringComparison.InvariantCulture)); } } }比较逻辑:
sb.AppendLine("2)数组元素需要实现IEquatable,主要是Eaquals的基于值比较的方法"); sb.AppendLine("3)改写Eaquals方法必须重写GetHashCode"); m_testComment = sb.ToString(); } public string TestComment { get { return m_testComment; } } public void Test() { CustomPerson[] firstDataSource = FakeDataGenerator.GetFirstTwoPersons(); CustomPerson[] seconDataSource = FakeDataGenerator.GetSeconTwoPersons(); if ((firstDataSource as IStructuralEquatable).Equals(seconDataSource, EqualityComparer<CustomPerson>.Default)) { TestResult = "Two arrays have same struct"; } else { TestResult = "Two arrays have diff structs"; } } public String TestResult { get; private set; } } }针对tuple,可以自己实现一个IEqualityComparer,然后传递进去即可。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace StructCompareOnArrayAndTuple { class TupleEqualityComparer: IEqualityComparer { public bool Equals(object x, object y) { //throw new NotImplementedException(); return x.Equals(y); } public int GetHashCode(object obj) { //throw new NotImplementedException(); return obj.GetHashCode(); } } class TupleComparer: IRainyTester { public TupleComparer() { StringBuilder sb = new StringBuilder(); sb.AppendLine("1) Use IStructuralCompare explicitly "); TestComment = sb.ToString(); } public String TestComment { get; private set; } public String TestResult { get; private set; } public void Test() { Tuple<Int16, String, CustomPerson> firstTuple = FakeDataGenerator.GetFirstTuple(); Tuple<Int16, String, CustomPerson> secondTuple = FakeDataGenerator.GetSecondTuple(); if ((firstTuple as IStructuralEquatable).Equals(secondTuple, new TupleEqualityComparer())) { TestResult = "Two tuple objects have same struct"; } else { TestResult = "Two tuple objects have diff structs"; } } } }结论:按照内容比较的关键是确保参与比较的对象有实现按值比较的逻辑,比如改写 Equals()方法IStructuralEquatable提供了按照值比较的接口
相关文章推荐
- iptables详解
- Android 利用addView 动态给Activity添加View组件
- 大道至简第一章感想
- UIMenuController的使用,对UILabel拷贝以及定制菜单
- 概要设计说明书——机房收费系统
- Runnable接口与Thread类的区别
- 【图像处理笔记】平滑空间滤波器
- NSMutableArray的基本使用
- google protocol buffer -2-.proto 定义规则
- 第三周项目一 顺序表的基本运算(1)
- java单例模式
- 上帝给谁的都不会太多
- 面试中常问的关于链表的题目
- Google Protocol Buffer 的使用和原理
- ASP.NET大文件上传方案
- Android中RelativeLayout各个属性
- Linux函数stat说明
- Java连接SQL Server
- Conclusion about Scene Change Detection
- JAVA-插入排序