2011-08-12 5 views
17

아래 예제와 같이 두 가지 일반 목록의 차이점을 찾으려고합니다. t1과 t2는 동일한 속성을 포함하지만 동일한 개체가 아니므로 IEqualityComparer를 구현해야합니다.Linq 사용자 정의 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;  
    } 
} 
+1

참조 IEnumerable.Except()와 사용자 정의 비교 자 - http://stackoverflow.com/q/1299513/485076 – sll

답변

4

내가 빨리 설명 할 수없는 사용하여 종료 솔루션을,하지만 그건 내 문제가되지 않습니다 그리고 내가 그것을 할 수 있다는 점에서 원하는 것을 재사용되며 특정 등급에 국한되지 않습니다.

Newtonsoft.Json 라이브러리를 사용하여 개체를 문자열로 serialize 한 다음 결과를 비교합니다. 이것은 또한 익명 클래스와 중첩 클래스를 사용하는 이점이 있습니다.

비교 작업 방식은 먼저 두 개체에서 GetHashCode를 호출하고 일치하는 경우이 루틴에서 일치하는 개체가 두 번 serialize된다는 것을 의미하는 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>()); 
    } 
} 

당신은 예를 들어, ExceptUsingJSonCompare를 제외하고 교환이 기능을 사용하려면

var differences = list2.ExceptUsingJSonCompare(list1); 
0

가장 좋은 방법은 고유/복합 각 키 objectand 다른 비트를 비교하기 만 가지고있는 핵심적인 부분을 비교 해달라고 방법이 시도입니다.

Reflection을 사용하면 클래스의 각 공용 속성 (매우 일반적인)을 통과하여 비교할 수 있지만 느려질 수 있습니다.

32

당신은 같은 것을 시도 할 수 :

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

동일한 유형의 목록에 개체를 추가하면 완벽하게 작동합니다. –

+1

감사합니다. IEqualityComparer를 사용하는 것보다 훨씬 간결합니다. – garyh

관련 문제