clr中將「相等性」分為兩類:「值相等性」和「引用相等性」。
值相等性:兩個變數所包含的數值相等。
引用相等性:兩個變數引用的是記憶體中的同乙個物件。
無論是操作符「==」,還是方法「equals()」,都傾向於表達這樣乙個原則:例:對於值型別,如果型別的值相等,就應該返回true;
對於引用型別,如果型別指向同乙個物件,則返回true。
1class
program222
}2324class
person
2527
public person(string
value)
2831 }
操作符「==」,還是方法「equals()」,都是可以被過載的。比如string型別,它是乙個特殊的引用型別,微軟覺得它的現實意義更接近於值型別,所以,再fcl中,string的比較被過載為針對」型別的值「的比較,而不是」引用本身「的比較。
例:
1string s1 = "aa"
;2string s2 = "aa"
;3 console.writeline(s1 == s2); //
true
4 console.writeline(s1.equals(s2)); //
true
5 s2 =s1;
6 console.writeline(s1 == s2); //
true
7 console.writeline(s1.equals(s2)); //
true
從設計上來說,很多自定義型別(尤其是自定義的引用型別)會存在和string型別比較接近的情況。如第乙個例子中的person類,再現實生活中,如果兩個人的id是相等的,我們就會認為兩者是同乙個人,這個時候就要過載equals方法了:
1class
person24
public person(string
value)58
//重寫object.equals(object o)
9public
override
bool equals(object
obj)
1013 }
這時再去比較兩個具有相同id的person物件的值就會返回true:
1object a = new person("
no1");2
object b = new person("
no1"
);3 console.writeline(a == b); //
false
4 console.writeline(a.equals(b)); //
true
此時,對於該類,可以用==判斷兩個例項是否為指向同乙個物件,用equals方法判斷兩個例項的值是否相等。
注意:fcl中提供了object.referenceequals方法來明確肯定是比較」引用相等性「。但是,重寫了equals方法,編譯器會提示乙個資訊:
」重寫 object.equals(object o) 但不重寫 object.gethashcode()」
這樣在使用fcl中的dictionary類時,可能隱含一些潛在的bug。
在上面的**基礎下,增加personmoreinfo類:
1class
personmoreinfo24
public personmoreinfo(string
value)
58 }
建立乙個dictionary,通過key尋找value:
1class
program213
static
void
addperson()
1421 }
執行結果:
122008501
2true
39008175
4 false
重寫了equals方法,所以在addperson方法裡的mike和main方法裡的mike屬於「值相等」,此時將「值」作為key放入dictinoary中,再在某處根據mike將對應的鍵mikevalue取出來。但是上面**執行結果卻是main方法中的mike沒有對應的mikevalue。原因是鍵值對的集合會根據key值的hashcode尋找value值。clr首先呼叫person類的gethashcode方法,因為person類沒有實現gethashcode方法,所以就呼叫object.gethashcode()。object為所有的clr型別都提供了gethashcode的預設實現,每new乙個物件,clr就會為該物件生成乙個固定的整型值,該值在物件的生存週期內不會改變,gethashcode方法就是實現對該整型值求hashcode。
所有上面的**中,兩個mike物件的hashcode是不一樣的,導致main方法裡的mike沒有對應的mikevalue。此時就要重寫gethashcode方法:
1class
person24
public person(string
value)58
//重寫object.equals(object o)
9public
override
bool equals(object
obj)
1013
//重寫object.gethashcode()
14public
override
intgethashcode()
1518 }
再次執行**得到以下結果:
1 -543127822true
3 -54312782
4 true
因為hashcode一般作為物件的特徵,在物件生存週期內賦值就不應改變,所以因基於那些唯讀屬性或特性生成hashcode。
gethashcode方法永遠只返回乙個整型int,而int的容量顯然無法滿足字串的容量,以下**會生成兩個同樣的hashcode:
1string s1 = "
nb0903100006";
2string s2 = "
nb0904140001";
3console.writeline(s1.gethashcode());
4 console.writeline(s2.gethashcode());
所以為了減少兩個不同型別之間根據字串產生相同的hashcode機率,要改進gethashcode方法:
1//重寫object.gethashcode()
2public
override
intgethashcode()
3
注意:重寫equals方法的同時,也應該實現乙個型別安全的介面iequatable
1class person : iequatable2
4public person(string
value)58
//重寫object.equals(object o)
9public
override
bool equals(object
obj)
1013
//重寫object.gethashcode()
14public
override
intgethashcode()
1519
//重寫iequatable.equals(t other)
20public
bool
equals(person other)
2124 }
參考:《編寫高質量**改善c#程式的157個建議》陸敏技
所有的惠普機器 區別對待
碰到乙個問題,公司有個hp的小機器,需要安裝centos,各種無法用u盤映象引導.期間試過各種辦法排除是不是u盤或者映象的問題,結果我一例外的,這兩者都沒問題.而後,又證明了機器硬體沒有問題.苦思冥想,在女朋友的分手通告下,想到了,是不是惠普本身的機器有問題.這一點,遇到一些相關的東西的.比如,惠普...
「區別對待」的一點想法
1 今天晚上和乙個大學同學通了 聊了一些事情。主要關於他辭職的事情。他辭職了,原因是他原本在公司做策劃,三個月可以轉正。還有乙個星期就可以轉正的時候,他老闆和他說轉正的話需要完成一項任務。做的好才可以轉正。然後他覺得不公平,不想被區別對待,只有他轉正的時候才要做任務,為什麼別人不需要完成任務就可以轉...
建議3 區別對待強制轉型與as和is
建議3 區別對待強制轉型與as和is 在闡述本建議之前,首先需要明確什麼是強制轉型,以及強制轉型意味著什麼。從語法結構上來看,類似下面的 就是強制轉型。secondtype secondtype firsttype 但是,強制轉型可能意味著兩件不同的事情 1 firsttype和secondtype...