在具有对象作为值的字典上使用除外

时间:2017-02-15 13:58:48

标签: c# .net linq dictionary except

直到现在我有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可能有一个简单的方法吗?

提前致谢!

2 个答案:

答案 0 :(得分: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());

答案 1 :(得分:1)

您需要在object.Equals(object other)中实施MyObject

根据您在对象之间定义相等性的方式,它可能如下所示:

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;
}

正如René在评论中所说,在实施GetHashCode时实施Equals通常是个好主意。