您的位置:首页 > 其它

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提供了按照值比较的接口

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: