Метод UnorderedEquals для сравнения 2 списков завершается ошибкой на булевых значениях - PullRequest
0 голосов
/ 17 октября 2018

Я использую расширение 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.Bizarre.

1 Ответ

0 голосов
/ 17 октября 2018

Ваш 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();
    }
}

BTW эта реализация GetHashCode может быть неоптимальной.Полезные советы по этому вопросу смотрите на Каков наилучший способ реализации этого составного метода GetHashCode ()


Примечание Ваша реализация UnorderedEquals может быть сокращенана это:

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