比较 2 个列表的 UnorderedEquals 方法在布尔值上失败
UnorderedEquals method to compare 2 lists fails on Boolean values
我使用 UnorderedEquals 扩展来比较 2 个列表。它运行良好,除非唯一的区别是布尔值。这是比较方法:
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 );
}
这是我的 Class 和 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( );
}
}
使用此代码,我应该能够从以下 运行 中获取错误值:
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;
}
如果我将任何布尔值更改为在两个列表之间不同,它总是 returns 为真。奇怪。
您的 comparer
没有考虑到所有字段。
目前您只比较 Id
。 IsDelegator
和 IsDelegate
呢?
你应该添加它们:
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();
}
}
顺便说一句 GetHashCode
的这个实现可能不是最优的。有关这方面的良好做法,请参阅 What is the best way to implement this composite GetHashCode()
备注
您对 UnorderedEquals
的实现可以缩短为:
return list1.Count() == list2.Count() &&
list1.All(e=> list2.Contains(e, comparer));
我使用 UnorderedEquals 扩展来比较 2 个列表。它运行良好,除非唯一的区别是布尔值。这是比较方法:
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 );
}
这是我的 Class 和 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( );
}
}
使用此代码,我应该能够从以下 运行 中获取错误值:
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;
}
如果我将任何布尔值更改为在两个列表之间不同,它总是 returns 为真。奇怪。
您的 comparer
没有考虑到所有字段。
目前您只比较 Id
。 IsDelegator
和 IsDelegate
呢?
你应该添加它们:
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();
}
}
顺便说一句 GetHashCode
的这个实现可能不是最优的。有关这方面的良好做法,请参阅 What is the best way to implement this composite GetHashCode()
备注
您对 UnorderedEquals
的实现可以缩短为:
return list1.Count() == list2.Count() &&
list1.All(e=> list2.Contains(e, comparer));