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

示例
下面的代碼示例使用 ReferenceEquals 確定兩個對象是否是相同的實例。
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
漂漂 閱讀(1895)
評論(0) 編輯 收藏 引用 所屬分類:
c#開發