在以对象为值的字典上使用 Except

Using Except on Dictionaries with Object as Value

直到现在我有 2 部 Dictionary<string, int> 类型的词典,需要使用 except 获取 dict1 中但不在 dict2 中的所有内容。示例:

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 的简单方法?

提前致谢!

您需要为您的 MyObject class 实施 GetHashCode()Equals 或为 KeyValuePair<string,MyObject>:[=17= 使用自定义相等比较器]

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());

您需要在 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;
}

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