2017-02-15 65 views
1

到現在爲止我有2個字典的Dictionary<string, int>類型,需要得到的所有內容在dict1但不在dict2使用except。例如:使用除對象爲字典的字典

Dictionary<string, int> dict1 = new Dictionary<string, int> 
{ 
    { "aaa", 1 }, 
    { "bbb", 2 } 
}; 

Dictionary<string, int> dict2 = new Dictionary<string, int> 
{ 
    { "aaa", 2 }, 
    { "bbb", 2 } 
}; 

var newDict = dict1.Except(dict2); 

newDict現在包含{ 「AAA」,1}這是我所期望的,因爲價值是不同的。

我的問題是,我們需要字典中的附加值,因此我們將Dictionary<string, int>更改爲Dictionary<string, MyObject>。當我現在使用except時,我沒有得到我想要的結果。例如:

public class MyObject 
{ 
    public MyObject(string name, int someNumber) 
    { 
     myString = name; 
     myInt = someNumber; 
    } 

    public string myString { get; set; } 
    public int myInt { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Dictionary<string, MyObject> dict1 = new Dictionary<string, MyObject> 
     { 
      { "aaa", new MyObject("abc", 1) }, 
      { "bbb", new MyObject("def", 2) } 
     }; 

     Dictionary<string, MyObject> dict2 = new Dictionary<string, MyObject> 
     { 
      { "aaa", new MyObject("abc", 2) }, 
      { "bbb", new MyObject("def", 2) } 
     }; 

     var newDict = dict1.Except(dict2); 
    } 
} 

newDict現在包含dict1所有KVP,但其實我只希望有從dict1中的第一項。我認爲這是因爲MyObject的值沒有被比較。我能做些什麼來解決這個問題? Linq有沒有簡單的方法?

在此先感謝!

+0

'KeyValuePair '使用['ValueType.Equals'](https://msdn.microsoft.com/en-us/library/2dts52z7(v = vs.110).aspx)來比較兩個字典項目。如果'TKey'和'TValue'是值類型,那麼這是有效的。如果兩者中的一個都是引用類型,則兩者必須是相同的引用,否則'Equals'返回'false'。既然你有兩個不同的實例('new MyObject ...'),它們是不相等的。 –

+0

覆蓋'MyObject'中的'Equals' +'GetHashCode' –

回答

1

您需要在您的MyObject中執行object.Equals(object other)

取決於你如何定義你的對象之間的平等,它看起來是這樣的:

public override bool Equals(object other) 
{ 
    if(!(other is MyObject)) 
    { 
     return false; 
    } 
    var o = other as MyObject; 
    return myString.Equals(o.myString) && myInt == o.myInt; 
} 

正如勒內說,在評論時,通常也實現GetHashCode當你實現Equals一個好主意。

+1

您還需要覆蓋'GetHashCode()'。否則,所有對象仍將被視爲不同。 –

+0

不,他們不會。在本地進行測試,它只用「Equals」工作。雖然我同意實現'GetHashCode'確實更清晰。只有當你使用對象作爲字典中的鍵時,你不需要哈希碼嗎? – germi

+2

@germi:這個原因很有趣。 ['ValueType.GetHashCode'](https://msdn.microsoft.com/en-us/library/system.valuetype.gethashcode(v = vs.110).aspx)只是返回第一個非靜態字段的哈希碼在這種類型中是「KeyValuePair 」中的關鍵。這對性能的原因很有意義。然後「Equals」可以檢查值是否相等。找到[這裏](https://referencesource.microsoft.com/#mscorlib/system/valuetype.cs,328f227c941517bf)和[here](https://referencesource.microsoft.com/#mscorlib/system/collections/generic/ keyvaluepair.cs,8585965bb176a426,引用)。 –

1

你需要或者實施GetHashCode()EqualsMyObject類或使用KeyValuePair<string,MyObject>自定義相等比較:

public class MyObjectComparer : IEqualityComparer<KeyValuePair<string,MyObject>> 
{ 
    public bool Equals(KeyValuePair<string, MyObject> obj1, KeyValuePair<string, MyObject> obj2) 
    { 
     if (obj1 == null) return obj2 == null; 
     if (obj2 == null) return false; 

     if (obj1.Key != obj2.Key) return false; 

     if (obj1.Value == null) return obj2.Value == null; 
     if (obj2.Value == null) return false; 

     return obj1.Value.myInt == obj2.Value.myInt && 
       obj1.Value.myString == obj2.Value.myString; 
    } 
    public int GetHashCode(MyObject obj) 
    { 
     if (obj == null) return 0; 
     int hash = obj.Key.GetHashCode(); 
     if (obj.Value == null) return hash; 
     return hash^obj.Value.myInt.GetHashCode()^obj.Value.myString.GetHashCode(); 
    } 
} 

現在這個比較器傳遞給Except()

var newDict = dict1.Except(dict2, new MyObjectComparer());