Welcome to Habanero Land!   Register  |  Login
You are here:   Blogs
  So, why do you need to register to download Habanero and access the additional materials? 
The success of any open source project is based on the community built around it. So go ahead, register / login and get involved!
Sep
23
Thu
Posted By Mark Whitfeld on Thursday, September 23, 2010
259 Views


Hi Everyone

I have made a class for doing equality comparison of classes using a delegate to retrieve the value to be compared.
I recon it would be quite useful to have around, so I’m just making you aware of it, and if any of you need it on another project we can put it into Habanero. (Unless we get enough requests to add it now in the Comments).

The constructor signature looks like this:
DelegatedValueEqualityComparer(Func<T,TValue> retrieveValueDelegate, IEqualityComparer<TValue> valueEqualityComparer = null)

An example of the construction in a real world Scenario (This constructs an Equality Comparer that will check Employee objects for Equality on the 'FullNames' property.) :
new DelegatedValueEqualityComparer<Employee, string>(employee => employee.FullNames);

It is also possible to provide the Equality Comparer for the comparison of the inner values. For example:
new DelegatedValueEqualityComparer<Employee, string>(employee => employee.FullNames, StringComparer.CurrentCultureIgnoreCase);

This will do the same comparison, but use the ignoring case comparer as opposed to the default comparer.
It is a pretty useful class to have, so if you use it, please let me know and request its presence in Habanero :)

Here is the code (I won't post the test class here for brevity):

/// <summary>
/// This impementation of an <see cref="IEqualityComparer{T}"/> uses the specified delegate to
/// get a value from an object and then uses the specified equality comparer to compare the retrieved values.
/// </summary>
/// <typeparam name="T">The type of the objects being compares for equality.</typeparam>
/// <typeparam name="TValue">The type of the inner value that will be compared.</typeparam>
public class DelegatedValueEqualityComparer<T, TValue> : IEqualityComparer, IEqualityComparer<T>
{
  /// <summary>
  /// The Delegate that will be used to retrieve the inner value from the object being compared.
  /// </summary>
  public Func<T, TValue> RetrieveValueDelegate { get; private set; }
  /// <summary>
  /// The Equality Comparer that will be used to compare the inner values once retrieved.
  /// </summary>
  public IEqualityComparer<TValue> ValueEqualityComparer { get; private set; }
 
  public DelegatedValueEqualityComparer(Func<T,TValue> retrieveValueDelegate, IEqualityComparer<TValue> valueEqualityComparer = null)
  {
  if (retrieveValueDelegate == null) throw new ArgumentNullException("retrieveValueDelegate");
  if (valueEqualityComparer == null) valueEqualityComparer = EqualityComparer<TValue>.Default;
  RetrieveValueDelegate = retrieveValueDelegate;
  ValueEqualityComparer = valueEqualityComparer;
  }
 
  #region Implementation of IEqualityComparer<T>
 
  /// <summary>
  /// Determines whether the specified objects are equal.
  /// </summary>
  /// <returns>
  /// true if the specified objects are equal; otherwise, false.
  /// </returns>
  /// <param name="x">The first object of type <paramref name="T"/> to compare.</param><param name="y">The second object of type <paramref name="T"/> to compare.</param>
  public virtual bool Equals(T x, T y)
  {
  var valueFromX = RetrieveValueDelegate(x);
  var valueFromY = RetrieveValueDelegate(y);
  return ValueEqualityComparer.Equals(valueFromX, valueFromY);
  }
 
  /// <summary>
  /// Returns a hash code for the specified object.
  /// </summary>
  /// <returns>
  /// A hash code for the specified object.
  /// </returns>
  /// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param><exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
  public virtual int GetHashCode(T obj)
  {
  var value = RetrieveValueDelegate(obj);
  return ValueEqualityComparer.GetHashCode(value);
  }
 
  #endregion
 
  #region Implementation of IEqualityComparer
 
  /// <summary>
  /// Determines whether the specified objects are equal.
  /// </summary>
  /// <returns>
  /// true if the specified objects are equal; otherwise, false.
  /// </returns>
  /// <param name="x">The first object to compare.</param><param name="y">The second object to compare.</param><exception cref="T:System.ArgumentException"><paramref name="x"/> and <paramref name="y"/> are of different types and neither one can handle comparisons with the other.</exception>
  bool IEqualityComparer.Equals(object x, object y)
  {
  return Equals((T)x, (T)y);
  }
 
  /// <summary>
  /// Returns a hash code for the specified object.
  /// </summary>
  /// <returns>
  /// A hash code for the specified object.
  /// </returns>
  /// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param><exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
  int IEqualityComparer.GetHashCode(object obj)
  {
  return GetHashCode((T)obj);
  }
 
  #endregion
}

 Top Viewed
 Habanero Cloud
 Archive
 

This website is best viewed in Internet Explorer 7 & 8; Firefox 3.6.11; Opera 10.63; & Safari 4.