爲什麼這段代碼返回true:爲什麼這兩個比較有不同的結果?
new Byte() == new Byte() // returns true
但是這個代碼返回false:
new Byte[0] == new Byte[0] // returns false
爲什麼這段代碼返回true:爲什麼這兩個比較有不同的結果?
new Byte() == new Byte() // returns true
但是這個代碼返回false:
new Byte[0] == new Byte[0] // returns false
因爲new Byte()
默認創建值類型,這是按值進行比較(它將返回byte
與價值0
)。和new Byte[0]
創建數組,這是一個引用類型,並通過引用進行比較(並且這兩個數組的實例將具有不同的引用)。
查看Value Types and Reference Types文章的詳細信息。
.NET中的字節數爲value types,這意味着當且僅當兩個字節具有相同的值時==
運算符才返回true。這也被稱爲value equality。
但是.NET中的數組是reference types,這意味着==
運算符返回true,當且僅當它們引用內存中的同一個數組實例時。這也被稱爲reference equality or identity。
請注意,==
運算符可以針對參考和值類型進行重載。例如,System.String
是引用類型,但字符串的==
運算符按順序比較數組中的每個字符。見Guidelines for Overloading Equals() and Operator == (C# Programming Guide)。
如果你想測試陣列是否含有完全相同的值(按順序),你應該考慮使用Enumerable.SequenceEqual
代替==
。
我認爲問題的關鍵是關於'=='運算符及其雙重性質。這個答案明顯涵蓋了這一點 –
最正確的答案,如果只用於「默認」 –
我喜歡對其他引用類型使用「默認」,但實際上是否可以更改數組類型的此行爲? –
比較引用實際上是比較指針地址,它們是不同的,即返回false和value地址的原因不管它比較值。
編譯器嘗試將值類型存儲在寄存器中,但由於寄存器編號有限,所以在堆棧中進一步存儲的值爲[Reference],而引用類型在堆棧中,但值在Heap中保存存儲器地址的地址。
這裏的比較比較堆棧中存在的值,在第一種情況下它們是相同的,而在第二種情況下,它是不同的堆地址。
這是一個相當混亂的答案。第一部分仍然使它看起來像參考比較,因爲您仍然使用「指針」一詞。使用圖形而不僅僅是文本也很煩人,因爲它使我很難編輯它以改善答案。 –
-1用於延續「值類型被存儲在堆棧中」的神話。我認爲這兩個「新的Byte()」調用的結果很可能存儲在寄存器中。 –
@Damien_The_Unbeliever註冊存儲取決於寄存器的可用性,否則它存儲在堆棧中,在這兩種情況下,值都是相同的。 –
還有就是==
操作者,其中兩個操作數都是byte
類型的過載和它被實現爲比較每個字節的值;在這種情況下,你有兩個零字節,它們是相等的。
的==
操作者不超載爲陣列,因此使用具有兩個操作數object
過載(因爲數組是object
類型的)在第二種情況下,其實現比較兩個對象的引用。對兩個數組的引用是不同的。
值得注意的是,這與byte
是一個值類型並且數組是引用類型的事實沒有任何關係(直接)。byte
的==
運算符具有值語義而只有,因爲運算符在該實現中存在特定的重載。如果超負荷不存在,那麼是沒有超載,其中兩個字節將是有效的操作數,因此代碼根本不會編譯。您可以通過創建自定義struct
並將其與==
運算符的兩個實例進行比較來輕鬆查看。代碼不會編譯,除非您爲這些類型提供您自己的==
實現。
見http://ericlippert.com/2014/01/15/inconsistent-equality/ –
我很驚訝沒有人發現這個問題的重複,因爲它是非常基本的**價值**類型詩句**參考* *輸入問題。 – P5Coder
我更加驚訝於它得到的票數 - 51現在。 – P5Coder