2017-02-15 64 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());