2017-07-07 51 views
0

之間的比較,假設我有這些對象字典兩個對象

var address = new Address("5455 Apache Trail", "Queen Creek", "AZ", "85243"); 
    var person = new Person("Jane", "Smith", address); 

我想用字典來檢查這些對象的平等,所以它的smiliar這樣

var dictionary = new Dictionary<object>{ [address] = address, [person] = person}; 
    Assert.IsTrue(dictionary.ContainsKey(new Address("5455 Apache Trail", "Queen Creek", "AZ", "85243"))); 
    Assert.IsTrue(dictionary.ContainsKey(new Person("Jane", "Smith", address))); 

然而,它總是返回作爲假。我在這裏錯過了什麼?

編輯

添加自定義詞典

public class Dictionary<T> : Dictionary<T, T> where T : class, new() 
{ 
} 

添加類

public abstract class BaseModel 
{ 
    public string Id { get; set; } 

    public BaseModel() 
    { 
    } 
} 

public class Address : BaseModel 
{ 
    public string Street { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string PostalCode { get; set; } 

    public Address() { } 

    public override bool Equals(object value) 
    { 
     if (value == null) 
      return false; 

     Address mod = value as Address; 

     return (mod != null) 
      && (Street == mod.Street) 
      && (City == mod.City) 
      && (PostalCode == mod.PostalCode) 
      && (State == mod.State); 
    } 

    public override int GetHashCode(){ 
     return base.GetHashCode(); 
    } 

    public Address(string street, string city, string state, string postalCode) { 
     this.Street = street; 
     this.City = city; 
     this.State = state; 
     this.PostalCode = postalCode; 
    } 
} 

public class Person : BaseModel 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public Address Address { get; set; } 

    public Person() { } 

    public Person(string firstName, string lastName, Address address) 
    { 
     this.FirstName = firstName; 
     this.LastName = lastName; 
     this.Address = address; 
    } 

    public override bool Equals(object value) 
    { 
     if (value == null) 
      return false; 

     Person mod = value as Person; 

     return (mod != null) 
      && (FirstName == mod.FirstName) 
      && (LastName == mod.LastName) 
      && (Address.Equals(mod.Address)); 
    } 


    public override int GetHashCode(){ 
     return base.GetHashCode(); 
    } 
} 
+0

@DavidL能正常工作在C#6,我也更新了我的問題,有一個自定義詞典 – vantian

回答

2

您需要傳遞適當的IEqualityComparer的實例。 如果你沒有通過任何比較器字典將使用默認的比較器。 (EqualityComparer.Default)。如果傳遞的參數是對象的相同實例,這將只返回true。您將必須創建自己的比較器

或者,您可以覆蓋要存儲在字典中的所有類中的GetHashCode和Equals。然後EqualityComparer.Default調用GetHashCode等於的適當覆蓋,然後設置您。如果您重寫這兩個函數,則不需要創建或將比較器傳遞給字典。

基於OP的編輯編輯:

請注意,您的執行的GetHashCode應與實施一致的Equals

a.Equals(B)=> b.Equals(一)=> a.GetHashCode()== b.GetHashCode()

在你的情況,因爲你仍然使用對象默認的GetHashCode上述條件不成立。

的GetHashCode的應等來實現:

public override int GetHashCode(){ 
     return this.FirstName.GetHashCode()^
       this.LastName.GetHashCode()^
       this.Address.GetHashCode(); 
    } 
+0

我重寫我的課程。你可以在這裏查看https://dotnetfiddle.net/v5wEji – vantian

+0

return base.GetHashCode(); 這是錯誤的。這仍然獲得將返回對象的不同實例的對象的通用哈希碼。您需要將其更改爲使用人員和地址對象字段中的哈希碼。 – bashrc

+0

真棒,它的工作。你有鏈接瞭解更多關於這個?我有點失去EqualityComparer以及如何正確使用'Equals()'和'GetHashCode()'。 – vantian

1

因爲你創建地址和人的新的參考,這將不匹配的關鍵,以下斷言陳述將起作用:

var dictionary = new Dictionary<object, object> { [address] = address, [person] = person }; 
Assert.IsTrue(dictionary.ContainsKey(address)); 
Assert.IsTrue(dictionary.ContainsKey(person)); 

UPDATE

如果新引用需要創建,使這本詞典使用EqualityComparer說法:

public class CustomEqualityComparer : IEqualityComparer<object> 
{ 
    public new bool Equals(object x, object y) 
    { 
     if (x is Address && y is Address) 
     { 
      var xAddress = x as Address; 
      var yAddress = y as Address; 
      return xAddress.Line1 == yAddress.Line1 && 
       xAddress.Line2 == yAddress.Line2 && 
       xAddress.Line3 == yAddress.Line3 && 
       xAddress.Line4 == yAddress.Line4; 
     } 

     if (x is Person && y is Person) 
     { 
      var xPerson = x as Person; 
      var yPerson = y as Person; 
      return xPerson.FirstName == yPerson.FirstName && 
       xPerson.LastName == yPerson.LastName; 
     } 

     return false; 
    } 

    public int GetHashCode(object obj) 
    { 
     if (obj is Address) 
     { 
      var address = obj as Address; 
      return address.Line1.GetHashCode()^
        address.Line2.GetHashCode()^
        address.Line3.GetHashCode()^
        address.Line4.GetHashCode(); 
     } 

     if (obj is Person) 
     { 
      var person = obj as Person; 
      return person.FirstName.GetHashCode()^
        person.LastName.GetHashCode(); 
     } 

     return obj.GetHashCode(); 
    } 
} 

然後在您的測試:

var dictionary = new Dictionary<object, object>(new CustomEqualityComparer()) 
     { [address] = address, [person] = person }; 
     Assert.IsTrue(dictionary.ContainsKey(new Address("5455 Apache Trail", "Queen Creek", "AZ", "85243"))); 
     Assert.IsTrue(dictionary.ContainsKey(person)); 

這是建議使用泛型類型而不是使用字典中的對象;考慮將您的密鑰從對象更改爲類型。

+0

到我要補充一個創造新reference.so我可以檢查在兩個不同的對象 – vantian

+0

之間請找到更新的答案,您基本上必須讓字典知道如何比較對象 – ashin

+0

@ashin儘管這與當前問題無關,但GetHashCode在您的答案中可能會導致某些類型的數據。 (例如{「bashrc」,「real」}會給出與{「bashrcreal」,「」}相同的哈希碼。) 相同的哈希碼進入同一個桶並被線性搜索。 – bashrc