欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#中Equality和Identity浅析

程序员文章站 2023-12-15 08:40:10
clr提供了可以区分类型的equality 和identity能力。 equality:如果两个对象是相同的类型,并且它们各自带有相同和等值的属性。(they are i...

clr提供了可以区分类型的equality 和identity能力。

equality:如果两个对象是相同的类型,并且它们各自带有相同和等值的属性。(they are instances of the same type and if each of the fields in one object matches the values of the fields in the other object)

equality必须满足三个必要条件:reflexive, symmetrics, and transitive
reflexive: 自身相等,及a==a 是永远成立的;
symmetrics: 对象性,及a==b成立那么b==a 也成立;
transitive: 传递性,及a==b, b==c成立那么a==c 也成立。

identity:两个对象必须相等(意味着他们共享同一块内存区域)(the two objects have the same values. – two objects are identical if they share an address in memory)

clr提供了至少四种方法来判断两个对象的等价性:

1.public static bool referenceequals(object left, object right);
2.public static bool equals(object left, object right);
3.public virtual bool equals(object right);
4.public static bool operator==(myclass left, myclass right);

referenceequals方法总是用来判断两个对象的identity的,不管是针对值类型还是引用类型。所以针对值类型,调用该方法总是会返回false,因为值类型作为这个方法的参数时会进行装箱操作。

静态的equals方法提供了判断两个对象的equality能力,在其实现的内部,调用了上述第三个虚拟的equals方法。和referenceequals一样,它们已经具备从底层判断两个对象的能力,我们从来不会覆写这两个方法。

实例equals方法也是用来区分两个对象的equality的。

对于引用类型的对象,它和referenceequals方法几乎是一样的。(因为判断两个引用类型是否的equality往往从identity上就可以区分)

而值类型的对象,我们不仅要判断他们具有相同的对象类型,还要判断他们的值相等。值类型从system.valuetype继承而来,valuetype已经重写了object.equals()方法,本来已经可以用来满足这些要求的。但是valuetype.equals()方法不是很有效,因为它必须要通过反射,在不知道具体的派生类型中,完成对它们所含有成员变量的值的比较。因此,建议在我们实现一个值类型的数据结构时,同时重写valuetype.equals()方法。

然而我们再回头看看引用类型,有时两个引用类型的对象往往被用来进行类似值类型的比较,比如:string类型,它虽然是引用类型,但它也重写了equals方法,因为我们拿它来判断两个string是否相同(equality),实际是希望判断它们是否具有相同的内容,这是一个value semantics。因此,我们建议在考虑实现一个用作值语义环境下的引用类型时候,也重写基类的object.equals()方法。

注:请参考mdsn或其它相关文档,如何实现equals方法的重写。

上面的图示给了很好的例子来区分equals和referenceequals方法,被用来做equility和identity判断的区别。

\== 运算符是可由类重载的运算符,它也是用来判断恒等的。 对于未重载= =的引用类型,会比较两个引用类型是否引用同一个对象。这跟引用类型的equals()方法是一样的。

对于未重载= =的值类型,该运算符会比较这两个值是否"按位"相等,即是否这两个值中的每个字段都相等。和equals方法一样,推荐在自定义值类型中,也要重载= =运算符,因为也存在反射在效率上的影响。

\== 运算符和equals方法的区别在于多态表现上。equals方法是重写,而= =运算符是被重载。这意味着除非编译器知道调用具体的重载版本,否则它只是调用未重载的= =版本。

上一篇:

下一篇: