原文地址:http://blog.csdn.net/wuchen_net/archive/2010/03/23/5409327.aspx
1. ReferenceEquals, == , Equals
Equals , == , ReferenceEquals都可以用于判斷兩個(gè)對(duì)象的個(gè)體是不是相等。
a) ReferenceEquals
ReferenceEquals是Object的靜態(tài)方法,用于比較兩個(gè)引用類型的對(duì)象是否是對(duì)于同一個(gè)對(duì)象的引用。對(duì)于值類型它總是返回false。(因?yàn)锽ox以后的對(duì)象總是不同的,hehe)
b) ==是一個(gè)可以重載的二元操作符,可以用于比較兩個(gè)對(duì)象是否相等。
對(duì)于內(nèi)置值類型,==判斷的是兩個(gè)對(duì)象的代數(shù)值是否相等。它會(huì)根據(jù)需要自動(dòng)進(jìn)行必要的類型轉(zhuǎn)換,并根據(jù)兩個(gè)對(duì)象的值是否相等返回true或者false。例如:
Int a = 100;
Double b =100;
If(a == b)
Console.WriteLine(“equal supports compare between different types!”);
上面這段程序?qū)?huì)輸出:
equal supports compare between different types!
而對(duì)于用戶定義的值類型,如果沒(méi)有重載==操作符,==將是不能夠使用的。例如:
Struct Userstruct1;
Userstruct1 a;
Userstruct1 b;
If(a == b)
Console.WriteLine(“can == reach this far?”)
上面的這段代碼是不能夠通過(guò)編譯的。可以通過(guò)重載使==作用于用戶定義的值類型。
對(duì)于引用類型,== 默認(rèn)的行為與ReferenceEquals的行為相同,僅有兩個(gè)對(duì)象指向同一個(gè)Reference的時(shí)候才返回true。但是.NET Framework中的類很多對(duì)==進(jìn)行了重載,例如String類的==與Equals的行為相同,判斷兩個(gè)字符串的內(nèi)容是否相等。所以在應(yīng)用中,對(duì)于 系統(tǒng)定義的引用類型建議不要使用==操作符,以免程序出現(xiàn)與預(yù)期不同的運(yùn)行結(jié)果。
c) Equals 作為Object內(nèi)置方法,Equals支持對(duì)于任意兩個(gè)CTSCommon Type System對(duì)象的比較。
Equals它有靜態(tài)方法和可重載的一個(gè)版本,下面的程序片斷解釋了這兩個(gè)方法的用法,
int a = 5;
int b = 5;
If(Object.Equals(a ,b))
// you can also use if(a.Equals(b))
{
Console.WriteLine(“a is equal to b”);
}
事實(shí)上,這兩個(gè)版本的結(jié)果完全相同,如果用戶重載了Equals,調(diào)用的都是用戶重載后的Equals。Equals的靜態(tài)方法的好處是可以不必考慮用于比較的對(duì)象是否為null。
Equals方法對(duì)于值類型和引用類型的定義不同,對(duì)于值類型,類型相同,并且數(shù)值相同(對(duì)于struct的每個(gè)成員都必須相同),則Equals返回 true,否則返回false。而對(duì)于引用類型,默認(rèn)的行為與ReferenceEquals的行為相同,僅有兩個(gè)對(duì)象指向同一個(gè)Reference的時(shí) 候才返回true。可以根據(jù)需要對(duì)Equals進(jìn)行重載,例如String類的Equals用于判斷兩個(gè)字符串的內(nèi)容是否相等。
//StringBuilder 類
//表示可變字符字符串。無(wú)法繼承此類。
StringBuilder a = new StringBuilder();
a.Append("the test a");
String s1 = a.ToString();
String s2 = "the test a";
if (s2 == s1)
Console.WriteLine("== returns true");
if (Object.Equals(s2, s1))
{
Console.WriteLine("equals returns true");
}
if (Object.ReferenceEquals(s2, s1))
{
Console.WriteLine("ReferenceEquals returns true");
}
這個(gè)實(shí)例將輸出:
== returns true
equals returns true
注:對(duì)于String類,直接聲明s1 = “the test a”的話,輸出結(jié)果將包含 "ReferenceEquals returns true",
因?yàn)槟J(rèn)的,String對(duì)于聲明的相同的字符串在堆上只保留一個(gè)Copy,所以s1與s2將會(huì)指向相同的Reference
。
http://javasky.bloghome.cn/posts/142567.html
在討論了運(yùn)算符,并簡(jiǎn)要介紹了等于運(yùn)算符后,就應(yīng)考慮在處理類和結(jié)構(gòu)的實(shí)例時(shí)相等意味著什么。理解對(duì)象相等比較的機(jī)制對(duì)編寫(xiě)邏輯表達(dá)式非常重要,另外,對(duì)實(shí)現(xiàn)運(yùn)算符重載和數(shù)據(jù)類型轉(zhuǎn)換也非常重要,本章的后面將討論運(yùn)算符重載。
對(duì)象相等比較的機(jī)制對(duì)于引用類型(類的實(shí)例)的比較和值類型(基本數(shù)據(jù)類型,結(jié)構(gòu)或枚舉的實(shí)例)的比較來(lái)說(shuō)是不同的。下面分別介紹引用類型和值類型的相等比較。
5.3.1 引用類型的相等比較
System.Object的一個(gè)初看上去令人驚訝的方面是它定義了3個(gè)不同的方法,來(lái)比較對(duì)象的相等性:ReferenceEquals()和Equals()的兩個(gè)版本。再加上比較運(yùn)算符==,實(shí)際上有4種進(jìn)行相等比較的方式。這些方法有一些微妙的區(qū)別,下面就介紹這些方法。
================================================================
下面的最明了
1. ReferenceEquals()方法
ReferenceEquals()是一個(gè)靜態(tài)方法,測(cè)試兩個(gè)引用是否指向類的同一個(gè)實(shí)例,即兩個(gè)引用是否包含內(nèi)存中的相同地址。作為靜態(tài)方法,它不能重寫(xiě),所以只能使用System.Object的實(shí)現(xiàn)代碼。如果提供的兩個(gè)引用指向同一個(gè)對(duì)象實(shí)例,ReferenceEquals()總是返回true,否則就返回false。但是它認(rèn)為null等于null:
SomeClass x, y;
x = new SomeClass();
y = new SomeClass();
bool B1 = ReferenceEquals(null, null); //return true
bool B2 = ReferenceEquals(null, x); //return false
bool B3 = ReferenceEquals(x, y); //return false because x and y
//point to different objects
2. 虛擬的Equals()方法
Equals()虛擬版本的System.Object實(shí)現(xiàn)代碼也比較引用。但因?yàn)檫@個(gè)方法是虛擬的,所以可以在自己的類中重寫(xiě)它,按值來(lái)比較對(duì)象。特別是如果希望類的實(shí)例用作字典中的鍵,就需要重寫(xiě)這個(gè)方法,以比較值。否則,根據(jù)重寫(xiě)Object.GetHashCode()的方式,包含對(duì)象的字典類要么不工作,要么工作的效率非常低。在重寫(xiě)Equals()方法時(shí)要注意,重寫(xiě)的代碼不會(huì)拋出異常。這是因?yàn)槿绻麙伋霎惓#值漕惥蜁?huì)出問(wèn)題,一些在內(nèi)部調(diào)用這個(gè)方法的.NET基類也可能出問(wèn)題。
3. 靜態(tài)的Equals()方法
Equals()的靜態(tài)版本與其虛擬實(shí)例版本的作用相同,其區(qū)別是靜態(tài)版本帶有兩個(gè)參數(shù),并對(duì)它們進(jìn)行相等比較。這個(gè)方法可以處理兩個(gè)對(duì)象中有一個(gè)是null的情況,因此,如果一個(gè)對(duì)象可能是null,這個(gè)方法就可以拋出異常,提供了額外的保護(hù)。靜態(tài)重載版本首先要檢查它傳送的引用是否為null。如果它們都是null,就返回true(因?yàn)閚ull與null相等)。如果只有一個(gè)引用是null,就返回false。如果兩個(gè)引用都指向某個(gè)對(duì)象,它就調(diào)用Equals()的虛擬實(shí)例版本。這表示在重寫(xiě)Equals()的實(shí)例版本時(shí),其效果相當(dāng)于也重寫(xiě)了靜態(tài)版本。[Page]
4. 比較運(yùn)算符==
最好將比較運(yùn)算符看作是嚴(yán)格值比較和嚴(yán)格引用比較之間的中間選項(xiàng)。在大多數(shù)情況下,下面的代碼:
bool b = (x == y); //x, y object references
表示比較引用。但是,如果把一些類看作值,其含義就會(huì)比較直觀。在這些情況下,最好重寫(xiě)比較運(yùn)算符,以執(zhí)行值的比較。后面將討論運(yùn)算符的重載,但顯然它的一個(gè)例子是System.String類,Microsoft重寫(xiě)了這個(gè)運(yùn)算符,比較字符串的內(nèi)容,而不是它們的引用。
5.3.2 值類型的相等比較
在進(jìn)行值類型的相等比較時(shí),采用與引用類型相同的規(guī)則:ReferenceEquals()用于比較引用,Equals()用于比較值,比較運(yùn)算符可以看作是一個(gè)中間項(xiàng)。但最大的區(qū)別是值類型需要裝箱,才能把它們轉(zhuǎn)換為引用,才能對(duì)它們執(zhí)行方法。另外,Microsoft已經(jīng)在System.ValueType類中重載了實(shí)例方法Equals(),以便對(duì)值類型進(jìn)行合適的相等測(cè)試。如果調(diào)用sA.Equals(sB),其中sA和sB是某個(gè)結(jié)構(gòu)的實(shí)例,則根據(jù)sA和sB是否在其所有的字段中包含相同的值,而返回true或false。另一方面,在默認(rèn)情況下,不能對(duì)自己的結(jié)構(gòu)重載==運(yùn)算符。在表達(dá)式中使用(sA==sB)會(huì)導(dǎo)致一個(gè)編譯錯(cuò)誤,除非在代碼中為結(jié)構(gòu)提供了==的重載版本。
另外,ReferenceEquals()在應(yīng)用于值類型時(shí),總是返回false,因?yàn)闉榱苏{(diào)用這個(gè)方法,值類型需要裝箱到對(duì)象中。即使使用下面的代碼:
bool b = ReferenceEquals(v, v); //v is a variable of some value type
也會(huì)返回false,因?yàn)樵谵D(zhuǎn)換每個(gè)參數(shù)時(shí),v都會(huì)被單獨(dú)裝箱,這意味著會(huì)得到不同的引用。調(diào)用ReferenceEquals()來(lái)比較值類型實(shí)際上沒(méi)有什么意義。
盡管System.ValueType提供的Equals()默認(rèn)重載肯定足以應(yīng)付絕大多數(shù)自定義的結(jié)構(gòu),但仍可以為自己的結(jié)構(gòu)重寫(xiě)它,以提高性能。另外,如果值類型包含作為字段的引用類型,就需要重寫(xiě)Equals(),以便為這些字段提供合適的語(yǔ)義,因?yàn)镋quals()的默認(rèn)重寫(xiě)版本僅比較它們的地址。
http://www.zxbc.cn/html/20070809/25909.html
====================================================================================================================
http://msdn.microsoft.com/zh-cn/library/bsc2ak47(VS.80).aspx
Object.Equals 方法 (Object)
確定指定的 Object 是否等于當(dāng)前的 Object。
參數(shù)
obj
與當(dāng)前的 Object 進(jìn)行比較的 Object。
返回值
如果指定的 Object 等于當(dāng)前的 Object,則為 true;否則為 false。
備注
Equals 的默認(rèn)實(shí)現(xiàn)僅支持引用相等,但派生類可重寫(xiě)此方法以支持值相等。
對(duì)于引用類型,相等定義為對(duì)象相等;即這些引用是否引用同一對(duì)象。對(duì)于值類型,相等定義為按位相等。ValueType 類支持值類型。
給實(shí)現(xiàn)者的說(shuō)明 此方法可由派生類重寫(xiě)。例如,如果兩個(gè)對(duì)象表示相同的值,則許多基數(shù)據(jù)類型返回 true;否則返回 false。 此方法僅比較基元和對(duì)象。若要比較更復(fù)雜的結(jié)構(gòu)(如對(duì)象數(shù)組),必須重寫(xiě)該方法。 下面的語(yǔ)句對(duì)于 Equals 方法的所有實(shí)現(xiàn)均必須為真。在列表中,x、y 和 z 表示不為 空引用(在 Visual Basic 中為 Nothing) 的對(duì)象引用。
除涉及浮點(diǎn)型的情況外,x.Equals(x) 都返回 true。請(qǐng)參見(jiàn) IEC 60559:1989, Binary Floating-point Arithmetic for Microprocessor Systems。
x.Equals(y) 返回與 y.Equals(x) 相同的值。
如果 x 和 y 都為 NaN,則 x.Equals(y) 返回 true。
當(dāng)且僅當(dāng) x.Equals(z) 返回 true 時(shí),(x.Equals(y) && y.Equals(z)) 才返回 true。
只要不修改 x 和 y 引用的對(duì)象,對(duì) x.Equals(y) 的相繼調(diào)用將返回相同的值。
x.Equals(空引用(在 Visual Basic 中為 Nothing)) 返回 false。
有關(guān)屬于 Equals 方法的其他必需行為,請(qǐng)參見(jiàn) GetHashCode。 Equals 的實(shí)現(xiàn)必須不引發(fā)異常。 對(duì)于某些類型的對(duì)象,最好讓 Equals 測(cè)試值相等性而非引用相等性。如果兩個(gè)對(duì)象具有相同的“值”,那么即使它們不是同一實(shí)例,這樣的 Equals 實(shí)現(xiàn)仍返回 true。類型實(shí)施者決定對(duì)象的“值”的構(gòu)成,但這通常是存儲(chǔ)在對(duì)象的實(shí)例變量中的部分或全部數(shù)據(jù)。例如,String 的值基于字符串的字符;對(duì)于兩個(gè)按同樣的順序包含完全相同的字符的字符串實(shí)例,String 類的 Equals 方法返回 true。 實(shí)現(xiàn) IComparable 的類型必須重寫(xiě) Equals。 重寫(xiě) Equals 的類型也必須重寫(xiě) GetHashCode;否則,Hashtable 可能不正常工作。 如果編程語(yǔ)言支持運(yùn)算符重載,并且您選擇了重載給定類型的相等運(yùn)算符,則該類型必須重寫(xiě) Equals 方法。這樣的 Equals 方法實(shí)現(xiàn)必須返回與相等運(yùn)算符相同的結(jié)果。遵照此準(zhǔn)則有助于確保使用 Equals 的類庫(kù)代碼(如 ArrayList 和 Hashtable)的行為方式與應(yīng)用程序代碼使用的相等運(yùn)算符的方式一致。 下面是針對(duì)實(shí)現(xiàn)值類型的準(zhǔn)則:
考慮重寫(xiě) Equals,以便在 ValueType 上獲得比 Equals 的默認(rèn)實(shí)現(xiàn)所提供的性能增強(qiáng)的性能。
如果重寫(xiě) Equals 并且語(yǔ)言支持運(yùn)算符重載,則必須重載值類型的相等運(yùn)算符。
下面是針對(duì)實(shí)現(xiàn)引用類型的準(zhǔn)則:
如果引用類型的語(yǔ)義是基于該類型表示某個(gè)(些)值的事實(shí),則考慮對(duì)該類型重寫(xiě) Equals。
即使大多數(shù)引用類型重寫(xiě) Equals,它們也必須不能重載相等運(yùn)算符。但是,如果實(shí)現(xiàn)的引用類型想要具有值語(yǔ)義(如復(fù)雜的數(shù)字類型),則必須重寫(xiě)相等運(yùn)算符。
using System;
public class Sample {
void Method() {
Object Obj1 = new Object();
Object Obj2 = new Object();
Console.WriteLine(Obj1.Equals(Obj2)); //===> false
Obj2 = Obj1;
Console.WriteLine(Obj1.Equals(Obj2)); //===> true
}
}
===================================================
Object.Equals 方法 (Object, Object)
確定指定的 Object 實(shí)例是否被視為相等。
參數(shù)
objA
要比較的第一個(gè) Object。
objB
要比較的第二個(gè) Object。
返回值
如果 objA 是與 objB 相同的實(shí)例,或者如果兩者均為空引用,或者如果 objA.Equals(objB) 返回 true,則為 true;否則為 false。
備注
Equals 的默認(rèn)實(shí)現(xiàn)僅支持引用相等,但派生類可重寫(xiě)此方法以支持值相等。
對(duì)于引用類型,相等定義為對(duì)象相等;即這些引用是否引用同一對(duì)象。對(duì)于值類型,相等定義為按位相等。ValueType 類支持值類型。
在調(diào)用 objA.Equals(objB) 前,此方法首先檢查兩個(gè)參數(shù)是否均為空引用。
示例
下面的代碼示例比較不同的對(duì)象。
C#
using System;


public class MyClass
{

public static void Main()
{
string s1 = "Tom";
string s2 = "Carol";

Console.WriteLine("Object.Equals(\"
{0}\", \"
{1}\") => {2}",
s1, s2, Object.Equals(s1, s2));

s1 = "Tom";
s2 = "Tom";

Console.WriteLine("Object.Equals(\"
{0}\", \"
{1}\") => {2}",
s1, s2, Object.Equals(s1, s2));

s1 = null;
s2 = "Tom";

Console.WriteLine("Object.Equals(null, \"
{1}\") => {2}",
s1, s2, Object.Equals(s1, s2));

s1 = "Carol";
s2 = null;

Console.WriteLine("Object.Equals(\"
{0}\", null) => {2}",
s1, s2, Object.Equals(s1, s2));

s1 = null;
s2 = null;
Console.WriteLine("Object.Equals(null, null) => {2}",
s1, s2, Object.Equals(s1, s2));
}

}/**//*

This code produces the following output.

Object.Equals("Tom", "Carol") => False
Object.Equals("Tom", "Tom") => True
Object.Equals(null, "Tom") => False
Object.Equals("Carol", null) => False
Object.Equals(null, null) => True

*/
Object.ReferenceEquals 方法
確定指定的 Object 實(shí)例是否是相同的實(shí)例。
參數(shù)
- objA
要比較的第一個(gè) Object。
- objB
要比較的第二個(gè) Object。
返回值
如果 objA 是與 objB 相同的實(shí)例,或者如果二者都為空引用,則為 true;否則為 false。

示例
下面的代碼示例使用 ReferenceEquals 確定兩個(gè)對(duì)象是否是相同的實(shí)例。
using System;


class MyClass
{


static void Main()
{
object o = null;
object p = null;
object q = new Object();

Console.WriteLine(Object.ReferenceEquals(o, p));
p = q;
Console.WriteLine(Object.ReferenceEquals(p, q));
Console.WriteLine(Object.ReferenceEquals(o, p));
}
}


/**//*

This code produces the following output.

True
True
False

*/
posted on 2010-08-22 23:16
漂漂 閱讀(1911)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
c#開(kāi)發(fā)