net框架通用对象操作

一.对象的等值性和惟一性

 System.Object类型提供了一个Equals的虚方法,其目的为判断两个对象是否有个相同的"值".


S/n?DfJvN0 1 class Object
#bMT.W6WC]b0
 2     {ITPUB个人空间/q@+\%A qB
 3         public virtual Boolean Equals(Object obj)ITPUB个人空间*g)~"?eP
 4         {
nSJYR+g2d0
 5             //如果两个引用指向的是同一个对象
@h4c1m qW0
 6             //它们肯定相等
9ffV|X)xm ] K0
 7             if(this==obj)ITPUB个人空间 {_9[FCLyau
 8             {
6} He z _c3L1J]0
 9                 return (true);ITPUB个人空间0S?3t9|@l
10             }
*f+RO(f6L~ V0
11 ITPUB个人空间 ~_CM,H7AbF
12             return (false);ITPUB个人空间lq!z,H rc#I&l7\2Y
13  
.^5AOq k/kI0
14         }ITPUB个人空间#d`#@ M2r {5uQ
15     }

这也许是最简单的方法.

但有时间,它提供的默认实现对我们来说是不够的,必须重写Equals方法.

自己写的时候,要遵循以下4条规则:

1.Equals方法必须是自反的.也就是说,x.Equals(x)必须返回true.

2.   Equals方法必须是对称的.也就是说,x.Equals(y)和y.Equals(x)必须返回同样的值.

3.Equals方法必须是可传递的.也就是说,如果x.Equals(y)和y.Equals(z)都返回true,那么x.Equals(z)也必须返回     true.

4. Equals方法必须是前后一致的.也就是说,如果两个对象的值没有发生变化,多次调用Equals方法的返回值应该相同.

(一)为基类没有重写Object.Equals方法的引用类型实现Equals


c Lo*r*y/n1u(E.M~0  class MyRefType:BaseType
x!fH"{+g0    {
|1Gn(H!|c,@0        RefType refobj;   
//引用类型
u{mE7A0
        ValueType valobj;  //值类型ITPUB个人空间#V%Dk FP P"T']
ITPUB个人空间(St~7^&J ci
        
public override bool Equals(object obj)ITPUB个人空间ya[.e dd,rP6R
        {ITPUB个人空间 d;u;T J@"N|i
            
//因为‘this’不为null,所以如果obj为null
| i0R*E"k3[3z9|'M1c0            
//那么两个对象将不可能相等
EdI*X'iaZ0
ITPUB个人空间4T4DVp/[2\g
            
if (obj == null)ITPUB个人空间 KL`;L3MUU
                
return false;
Q2s+D}z'|0
K`N!?[/di0            
//如果两个对象的类型不同,那么它们不可能相等
1{me YoqJ]0
            if (this.GetType() != obj.GetType())ITPUB个人空间3By$?cd+j
                
return false;
(C%n `eP1Z0            
//将obj转型为定义的类型以访问其中的字段,这里的ITPUB个人空间F'm4V/ciE{2z8K!r
            
//转型不会失败,因为已经知道两个对象是同一类型
0\v].U i&x[B0

BB)hgY1Y'S0            MyRefType other
=(MyRefType)obj;ITPUB个人空间~9O Lz;F%p&Vl!C

]NB@H@0            
//比较其中的引用类型字段
'TfkW m0
            if (!Object.Equals(refobj, other.refobj))ITPUB个人空间)bMe pENZ+W
                
return false;ITPUB个人空间4h WC;|5c0`$`G;Eu _
ITPUB个人空间"_#u6B^ @h,?
            
//比较其中的值类型字段
:jc F9yCE:XXB0
            if (!valobj.Equals(other.valobj))
G5I Hn,w0                
return false;ITPUB个人空间n&s^ vGxW6|T

he&K$t"ve}q0            
return true;  //到这里两个对象才相等ITPUB个人空间i+vs5X3Q0j
        }ITPUB个人空间S.\ F$C*K|0~o
    }

这要注意的:

1.要比较引用类型的字段,我们应该调用Object的静态方法Equals方法.

    Objext的静态方法Equals方法是一个比较两个引用类型对象的辅助方法.采用这种方法比较,是因为即使两个字段出现了值为null的情况,代码仍会正常运行.

2.要比较值类型的字段,应该调用该字段类型的Equals方法.不应该调用Object的静态方法Equals方法.因为值类型对象的值永远不可能为null,并且调用Object的静态方法Equals会对值类型对象执行装箱操作.

(二)为基类重写了Object.Equals方法的引用类型实现Equals

 

ITPUB个人空间t XH(dx$c0z^p
class MyRefType:BaseType
Z2nw2_;Q0    {ITPUB个人空间 u@3U,pv\
        RefType refobj;   
//引用类型
aQ+_4x%E"Hy0
        ValueType valobj;  //值类型
m#|Gz8m5q.w]9^Kg0

uA;X3iHJN0        
public override bool Equals(object obj)ITPUB个人空间2keNRm,cJ{,z"V
        {ITPUB个人空间c*Z)pOIo&Dm
            
//首先让基类型比较其中的字段
BM`F5g0
            if (!base.Equals(obj))
ywa RKzk-I0                
return false;
2Lq]S]0
E \b)HvZ&i"O.iW#i0            
//因为‘this’不为null,所以如果obj为nullITPUB个人空间 uf4LbE j
            
//那么两个对象将不可能相等
,n5S T-W'\ MS0

a"QHz3oi!rS&l0W/n0            
if (obj == null)ITPUB个人空间q ZC!`:A
                
return false;
H!w4\g[0
&\3t_s_0P6ep0            
//如果两个对象的类型不同,那么它们不可能相等
8\$z4u[tC0
            if (this.GetType() != obj.GetType())
2U0| YI&K~`#@+z_0                
return false;ITPUB个人空间~"Yd%^&VE'x7S
            
//将obj转型为定义的类型以访问其中的字段,这里的ITPUB个人空间9RAtX#Pk!\ L_:X%H9F!I
            
//转型不会失败,因为已经知道两个对象是同一类型
p&G;\ aS#p/w0
ITPUB个人空间n,ze;Q x-i^%}
            MyRefType other
=(MyRefType)obj;ITPUB个人空间N.F[,r0nb%^ n$T2Tk
ITPUB个人空间&]RIN0B2P3G8[
            
//比较其中的引用类型字段ITPUB个人空间/j,a8?/o9CQrkf
            if (!Object.Equals(refobj, other.refobj))
vdD ]S6[ q0                
return false;ITPUB个人空间HA*ng WeDc!^y

^W4Q_&M2ph r0            
//比较其中的值类型字段ITPUB个人空间,{4C Eq O)a.fi
            if (!valobj.Equals(other.valobj))
B.N,yH9@zLf2F0                
return false;ITPUB个人空间;r7|#t+he,lT]x G
ITPUB个人空间)mxn&|7d*\ \%n L3j
            
return true;  //到这里两个对象才相等ITPUB个人空间H%_!s] g,v!X|
        }ITPUB个人空间K0v:v m^(e8p
    }

 

如果调用base.Equals会导致调用Object.Equals方法,那么就不应该再调用它.这一点很重要.因为只有在两个引用指向同一个对象时,Object.Equals方法才会返回true.如果两个引用没有指向同一个对象,那么它将返回false.这样我们实现的Equals方法将总是返回false.

 当然,如果我们定义的类型直接继承自Object,我们就应该象第一段代码那样来实现Equals.如果我们定义的类型不是直接继承自Object,我们必须首先确定该类型的基类型是否重写了Equals方法.如果其中任何一个基类型重写了Equals方法,那么我们就应该象这段代码先base.Equals方法.



作者:水木    
 
原文地址:https://www.cnblogs.com/hsapphire/p/1646306.html