I use an UnorderedEquals extension to compare 2 lists. It works well, except where the only difference is a Boolean value. Here is the compare method:
public static bool UnorderedEquals<T>( this IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer )
{
var d = new Dictionary<T, int>( comparer );
foreach( T s in list1 )
{
if( d.ContainsKey( s ) )
{
d[s]++;
}
else
{
d.Add( s, 1 );
}
}
foreach( T s in list2 )
{
if( d.ContainsKey( s ) )
{
d[s]--;
}
else
{
return false;
}
}
return d.Values.All( c => c == 0 );
}
Here is my Class and IEqualityComparer:
public class SelectedEntities
{
public int Id { get; set; }
public bool IsDelegator { get; set; }
public bool IsDelegate { get; set; }
}
public class SelectedEntitiesEqualityComparer : IEqualityComparer<SelectedEntities>
{
public bool Equals( SelectedEntities x, SelectedEntities y )
{
if( object.ReferenceEquals( x, y ) )
return true;
if( x == null || y == null )
return false;
return x.Id.Equals( y.Id );
}
public int GetHashCode( SelectedEntities obj )
{
return obj.Id.GetHashCode( );
}
}
Using this code, I should be able to get a false value from running the following:
private bool CompareLists( )
{
bool result = false;
var list1 = new List<SelectedEntities>( );
var list2 = new List<SelectedEntities>( );
list1.Add( new SelectedEntities { Id = 1, IsDelegator = false, IsDelegate = true } );
list1.Add( new SelectedEntities { Id = 2, IsDelegator = false, IsDelegate = true } );
list2.Add( new SelectedEntities { Id = 1, IsDelegator = false, IsDelegate = true } );
list2.Add( new SelectedEntities { Id = 2, IsDelegator = false, IsDelegate = false } ); // this is different
result = list1.UnorderedEquals( list2, new SelectedEntitiesEqualityComparer( ) );
return result;
}
If I change any of the Boolean values to be different between the two list, it always returns true. Bizarre.
Your comparer
does not take into account all the fields.
Currently you only compare Id
. What about IsDelegator
and IsDelegate
?
You should add them:
public class SelectedEntitiesEqualityComparer : IEqualityComparer<SelectedEntities>
{
public bool Equals( SelectedEntities x, SelectedEntities y )
{
if( object.ReferenceEquals( x, y ) )
return true;
if( x == null || y == null )
return false;
return x.Id.Equals( y.Id ) &&
x.IsDelegator.Equals(y.IsDelegator) &&
x.IsDelegate.Equals(y.IsDelegate);
}
public int GetHashCode( SelectedEntities obj )
{
return obj.Id.GetHashCode( )^
obj.IsDelegator.GetHashCode()^
obj.IsDelegate.GetHashCode();
}
}
BTW this implementation of GetHashCode
might not be optimal. For good practices regarding this look at What is the best way to implement this composite GetHashCode()
Note
Your implementation of UnorderedEquals
can be shortened to this:
return list1.Count() == list2.Count() &&
list1.All(e=> list2.Contains(e, comparer));