Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jun 30th, 2012  |  syntax: None  |  size: 3.39 KB  |  hits: 13  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. Generic PropertyEqualityComparer<T>
  2. public sealed class PropertyEqualityComparer<T> : IEqualityComparer<T>
  3. {
  4.     private readonly Type _iequatable = Type.GetType("System.IEquatable`1", false, true);
  5.     private readonly PropertyInfo _property;
  6.  
  7.     public PropertyEqualityComparer(string property)
  8.     {
  9.         PropertyInfo propInfos = typeof(T).GetProperty(property);
  10.         if (propInfos == null)
  11.         {
  12.             throw new ArgumentNullException();
  13.         }
  14.  
  15.         // Ensure Property is Equatable (override of HashCode)
  16.         if (propInfos.PropertyType.IsValueType
  17.             || (!propInfos.PropertyType.IsValueType
  18.                 && propInfos.PropertyType.GetInterfaces().Any(type => type.Name == _iequatable.Name)))
  19.         {
  20.             _property = propInfos;
  21.         }
  22.         else
  23.         {
  24.             throw new ArgumentException();
  25.         }
  26.     }
  27.  
  28.     public bool Equals(T x, T y)
  29.     {
  30.         var xValue = _property.GetValue(x, null);
  31.         var yValue = _property.GetValue(y, null);
  32.  
  33.         return xValue.Equals(yValue);
  34.     }
  35.  
  36.     public int GetHashCode(T obj)
  37.     {
  38.         return _property.GetValue(obj, null).GetHashCode();
  39.     }
  40. }
  41.        
  42. public sealed class A
  43. {
  44.     private string _s1;
  45.     private B _b;
  46.  
  47.     public A(string s1, B b)
  48.     {
  49.         _s1 = s1;
  50.         _b = b;
  51.     }
  52.  
  53.     public string S1
  54.     {
  55.         get { return _s1; }
  56.         set { _s1 = value; }
  57.     }
  58.  
  59.     public B B
  60.     {
  61.         get { return _b; }
  62.         set { _b = value; }
  63.     }
  64. }
  65.  
  66. public sealed class B : IEquatable<B>
  67. {
  68.     private string _s;
  69.  
  70.     public string S
  71.     {
  72.       get { return _s; }
  73.       set { _s = value; }
  74.     }
  75.  
  76.     public B(string s)
  77.     {
  78.         S = s;
  79.     }
  80.  
  81.     public override int GetHashCode()
  82.     {
  83.         return S.GetHashCode();
  84.     }
  85.  
  86.     public override bool Equals(object obj)
  87.     {
  88.         return Equals(obj as B);
  89.     }
  90.  
  91.     public bool Equals(B other)
  92.     {
  93.         return (other == null)
  94.             ? false
  95.             : this.S == other.S;
  96.     }
  97. }
  98.        
  99. B b = new B("baby");
  100. A[] __a = { new A("first", b), new A("second", b), new A("third", b)};
  101. PropertyEqualityComparer<A> aComparer = new PropertyEqualityComparer<A>("B");
  102.  
  103. var vDistinct = __a.Distinct(aComparer).ToArray();
  104. // vDistinct = __a[0] { first, baby }
  105. var vContains = __a.Contains(new A("a", new B("baby")), aComparer);
  106. // True
  107. vContains = __a.Contains(new A("b", new B("foobar")), aComparer);
  108. // False
  109.        
  110. var comparer = new ProjectionEqualityComparer<A, B>(a => a.B);
  111.  
  112. // ...
  113.  
  114. public sealed class ProjectionEqualityComparer<TSource, TKey>
  115.     : EqualityComparer<TSource>
  116. {
  117.     private readonly Func<TSource, TKey> _keySelector;
  118.     private readonly IEqualityComparer<TKey> _keyComparer;
  119.  
  120.     public ProjectionEqualityComparer(Func<TSource, TKey> keySelector,
  121.         IEqualityComparer<TKey> keyComparer = null)
  122.     {
  123.         if (keySelector == null)
  124.             throw new ArgumentNullException("keySelector");
  125.  
  126.         _keySelector = keySelector;
  127.         _keyComparer = keyComparer ?? EqualityComparer<TKey>.Default;
  128.     }
  129.  
  130.     public override bool Equals(TSource x, TSource y)
  131.     {
  132.         if (x == null)
  133.             return (y == null);
  134.  
  135.         if (y == null)
  136.             return false;
  137.  
  138.         return _keyComparer.Equals(_keySelector(x), _keySelector(y));
  139.     }
  140.  
  141.     public override int GetHashCode(TSource obj)
  142.     {
  143.         if (obj == null)
  144.            throw new ArgumentNullException("obj");
  145.  
  146.         return _keyComparer.GetHashCode(_keySelector(obj));
  147.     }
  148. }