【问题标题】:Linq Except with custom IEqualityComparerLinq 自定义 IEqualityComparer 除外
【发布时间】:2011-08-12 15:05:09
【问题描述】:

我试图找出两个通用列表之间的区别,如下例所示。 即使 t1 和 t2 包含相同的属性,它们也不是同一个对象,所以我需要实现一个 IEqualityComparer。

这似乎适用于这个例子,但真正的类有几个其他属性,我也需要对其他几个类做同样的事情。

所以我想知道我是否在重新发明轮子?

有比较简单的方法来比较两个对象的所有属性吗?目前,我真的只需要处理包含简单类型的类,但如果我有一个可以处理包含其他类实例的类的比较器,那就太好了。

void Main()
{
    var t1 = new Sizes { Name = "Test" , Size = 1} ;
    var t2 = new Sizes { Name = "Test" , Size = 1} ;

    var list1 = new List<Sizes>();
    var list2 = new List<Sizes>();
    list1.Add(t1);
    list2.Add(t2);

    var differences = list2.Except(list1 , new SizesComparer());    
    // differences should be empty.
}


public class Sizes  
{
    public string Name { get;  set; }
    public int    Size { get;  set; }
}

public class SizesComparer : IEqualityComparer<Sizes>   
{
    bool IEqualityComparer<Sizes>.Equals(Sizes x, Sizes y)
    {            
        return (x.Name.Equals(y.Name) && x.Size.Equals(y.Size));        
    }

    int IEqualityComparer<Sizes>.GetHashCode(Sizes obj)
    {
        if (Object.ReferenceEquals(obj, null))
            return 0;               

        return obj.Name.GetHashCode() + obj.Size;       
    }
}

【问题讨论】:

标签: c# linq-to-objects iequalitycomparer


【解决方案1】:

你可以试试这样的:

var differences = list2.Where(l2 => 
    !list1.Any(l1 => l1.Name == l2.Name && l1.Size == l2.Size));

或者,如果您愿意:

var differences = list2.Where(l2 => 
    list1.All(l1 => l1.Name != l2.Name || l1.Size != l2.Size));

【讨论】:

  • 如果您将对象添加到相同类型的列表中,这将非常有效。
  • 谢谢。比使用 IEqualityComparer 更简洁
【解决方案2】:

我最终使用的解决方案不能被描述为快速,但这不是我关心的问题,它可以满足我的需求,因为它可以重复使用并且不限于任何特定的类。

它使用 Newtonsoft.Json 库将对象序列化为字符串,然后比较结果。这还具有使用匿名类和嵌套类的优势。

我假设比较的工作方式是它首先在两个对象上调用 GetHashCode,如果它们匹配,则调用 Equals,这在此例程中意味着匹配的对象将被序列化两次。

public class JSonEqualityComparer<T> : IEqualityComparer<T>
{   
    public bool Equals(T x, T y)
    {           
        return String.Equals
        ( 
            Newtonsoft.Json.JsonConvert.SerializeObject(x), 
            Newtonsoft.Json.JsonConvert.SerializeObject(y)
        );                  
    }

    public int GetHashCode(T obj)
    {                           
        return Newtonsoft.Json.JsonConvert.SerializeObject(obj).GetHashCode();          
    }               
}       


public static partial class LinqExtensions
{
    public static IEnumerable<T> ExceptUsingJSonCompare<T>
        (this IEnumerable<T> first, IEnumerable<T> second)
    {   
        return first.Except(second, new JSonEqualityComparer<T>());
    }
}

要使用它,您可以将 except 与 exceptUsingJSonCompare 交换,例如:

var differences = list2.ExceptUsingJSonCompare(list1); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    相关资源
    最近更新 更多