2013-01-25 56 views
4

這是一個基本類型的問題,原諒我是如此的業餘。在C中的兩個對象的平等比較#

案例1:

Employee _emp1 = new Employee(); 
Employee _emp2 = _emp1; 
_emp1.Equals(_emp2) ==> RETURNS a True !! 

案例2:

Employee _emp1 = new Employee(); 
Employee _emp2 = new Employee(); 
_emp1.Equals(_emp2) ==> RETURNS a False !! 

你能解釋我interms內存映射和分配的角度看上面的對比方法和原因是什麼?

+3

案例1令您驚訝嗎? C++背景? –

+0

@Damien_The_Unbeliever我想是的,賓果! – Cris

+1

-1抱歉,但我不認爲SO是這個級別問題的地方。這種事情已經在MSDN和博客中引起了麻煩。 – DeanOC

回答

3
Employee _emp1 = new Employee(); 

每次你在堆和棧分配新的內存。

意味着_emp1在內存指着堆說,1212

現在你有第二次發言

Employee _emp2 = new Employee(); 

所以,再一次新的價值_emp2說1414堆中的​​價值。

這就是爲什麼_emp1.Equals(_emp2)在這裏返回false。

當你說

_emp1 = _emp2 

你分配在兩個相同的值。

3

「這個蘋果屬於喬,這個梨屬於同一個人,這個蘋果的主人是這個梨主人的同一個人嗎?是的。」

「這個蘋果屬於蘇珊,這個梨屬於蘇珊,這個蘋果的主人是這個梨主人的同一個人嗎?不,他們恰好都被稱爲蘇珊。

2

您應該創建自己的Equals方法。默認EqualsObject類被調用,基本上檢查這兩個引用是否指向一個對象(即調用Object.ReferenceEqual(object, object)

9

簡而言之,默認比較器比較對象實例。

  • 在你的第一個例子中,無論是_emp1_emp2被指向的Employee因此Equals返回true相同的實例。

  • 在你的第二個例子中,你創建了兩個Employee對象,_emp1_emp2是兩個明顯不同的對象。因此,Equals返回false。


注意拷貝構造函數是引用類型不隱式調用。是你做的事:

Employee _emp1 = new Employee(); 
Employee _emp2 = new Employee(_emp1); //or _emp1.Clone() if that is implemented 

然後Equals使用默認的比較將返回false,因爲它們是兩個唯一對象。

另請注意,對於值類型,此行爲是不一樣


而且,如果你(你應該)覆蓋的EqualsCompareTo默認行爲,所有上述變得毫無意義。一個標準的技術可能是(假設一點點):

public bool Equals(object rhs) 
{ 
    var rhsEmployee = rhs as Employee; 
    if(rhsEmployee == null) return false; 

    return this.Equals(rhsEmployee); 
} 

public bool Equals(Employee rhs) 
{ 
    return this.EmployeeId == rhs.EmployeeId; 
} 

進一步閱讀:

+0

在您的第一個項目符號中,您的意思是說_emp1和_emp2都指向相同的內存位置。並在第二個_emp1和_emp2指向兩個不同的內存位置。那麼這和Stacks,堆有什麼關係? –

+1

@ LetsKickSomeAssin.net在語義上它是一回事,是的。但是,在託管世界中,我們傾向於避免直接談論關於記憶的事情,因爲我們通常沒有直接控制記憶。但是,是的,它正在檢查比較兩個指針值的[Object.ReferenceEquals](http://msdn.microsoft.com/en-us/library/system.object.referenceequals.aspx)。 –

+0

這將不會編譯,因爲編譯器拒絕將'null'轉換爲'bool'。如果另一個實例不是'Employee','Equals'應該返回'false'。 – Nuffin

1

Employee,沒有實現它自己的.Equals()方法,那麼它使用的是Object.Equals(),它只是比較引用。在情況1中,分配時兩個參考值相等。

如果要將Employee對象與其內部屬性進行比較,則應該實現自己的.Equals()方法,如果所有這些屬性值都匹配,則返回true;否則返回false。

1

沒有辦法將僱員的兩個單獨實例等同起來,您需要一種方法來將他們是否相等,因爲他們是單獨的實例。在情況一中,實例是相同的,並且_emp2_emp1您可以通過執行IEquatable<T>接口來完成此操作。

public class Employee : IEquatable<Employee> 
{ 
    public int Id { get; set; } 

    public bool Equals(Employee other) 
    { 
    return other.Id == Id; 
    } 
} 

然後就可以做到這一點,你有new Employee()

Employee e = new Employee() { Id = 1 }; 
Employee e2 = new Employee() { Id = 1 }; 
//Returns true 
bool b = e.Equals(e2); 
1

當您編寫Employee _emp1時,您正在分配內存,該內存用於存儲指向另一個包含Employee實例的內存的指針。

new Employee();分配一個新的內存填充它與一個員工的實例,並返回你這個內存(指針)的地址。比如說,1234567.因此,在執行Employee _emp1 = new Employee();之後,您的_emp1等於1234567,而1234567指向的內存包含您的員工。

然後你執行Employee _emp2 = _emp1;,結果是有另一塊內存能夠包含一個地址到一個包含Employee實例(_emp2)的內存,它也等於1234567。這一點,當你執行_emp1.Equals(_emp2)時,結果是真實的,因爲你的兩個變量都指向同一塊內存。

在第二種情況下,Employee的另一個實例被創建並放入不同的內存中(例如類似於7654321),並且該地址被指定爲_emp2,因此與_emp1不同。