LINQ join не использует Equals из предоставленного EqualityComparer, вместо него используется GetHashCode - PullRequest
0 голосов
/ 22 февраля 2012

при передаче EqualityComparer в качестве последнего параметра методу Linq Join он не использует метод Equals, а по какой-то причине использует GetHashCode для сравнения элементов.

Возможно ли сделать так, чтобы вместо него использовался Equals?

        var ss = new string[] { "aa", "bb", "cc" };
        var zz = new string[] { "aa", "zz", "cc" };

        var res = ss
            .Join(zz, 
                o => o, 
                i => i, 
                (i, o) => i + o, 
                new GenericEqualityComparer<String>((x,y) => x == y))
            .ToList();

Ответы [ 2 ]

1 голос
/ 22 февраля 2012

Когда IEqualityComparer<T> сравнивается с объектами, он сначала сравнивает их хеш-коды.Только если они равны, метод Equals используется для уточнения сравнения.Так что в вашем случае он должен по крайней мере дважды нажать Equals.

Чтобы продемонстрировать, что делает EqualityComparer, я сделал небольшой фрагмент кода в Linqpad:

void Main()
{
    var ss = new string[] { "aa1", "bb1", "cc1" };
    var zz = new string[] { "aa2", "aa3", "zz2", "cc2" };

    var res = ss.Join(zz,  o => o, i => i, (i, o) => i + o,
        new SubstringComparer()).ToList();
}

public class SubstringComparer : IEqualityComparer<string>
{
    public bool Equals(string left, string right)
    {
        string.Format("{0} - {1}", left, right).Dump();
        return left.Substring(0,2) == right.Substring(0,2);
    }

    public int GetHashCode(string value)
    {
        value.Dump();
        return value.Substring(0,2).GetHashCode();
    }
}

Так что строки равны, если ихпервые два символа равны.Вывод:

aa2
aa3
aa2 - aa3
zz2
cc2
aa1
aa2 - aa1
bb1
cc1
cc2 - cc1

И полученный список:

aa1aa2
aa1aa3
cc1cc2

Вы видите, чтосначала сравнивается второй список (я не уверен, почему, кстати, может быть, кешируются хэш-коды), а затем пары.1037 * он как-то всегда генерирует уникальный хеш-код, который, я думаю, должен быть ошибкой.Если это не всегда использует Equals, вот объяснение.И если вы хотите, чтобы компаратор всегда использовал Equals, вы должны сделать так, чтобы он всегда возвращал идентичный хеш-код (что, конечно, неэффективно).

0 голосов
/ 22 февраля 2012

https://stackoverflow.com/a/3719802/136967

имеет очень хорошее объяснение.В основном, сравнения выполняются с использованием Equals (), но GetHashCode () используется кодом Linq при выполнении обработки, и если он не реализован правильно, он даст странные ответы.

hth,Алан.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...