用于比较2个列表的UnorderedEquals方法在布尔值上失败

时间:2018-10-17 07:52:53

标签: c# list compare iequalitycomparer

我使用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 );
    }

这是我的课程和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;
    }

如果我将两个列表中的任何布尔值更改为不同,它将始终返回true。奇怪。

1 个答案:

答案 0 :(得分:2)

您的comparer未考虑所有字段。 目前,您仅比较IdIsDelegatorIsDelegate呢?

您应该添加它们:

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 这种GetHashCode的实现可能不是最佳的。有关与此相关的良好做法,请查看What is the best way to implement this composite GetHashCode()


注意 您可以将UnorderedEquals的实现简化为:

return list1.Count() == list2.Count() &&
       list1.All(e=> list2.Contains(e, comparer));