Правильный способ создания собственного компаратора для linq join - PullRequest
0 голосов
/ 08 октября 2019

У меня проблемы с созданием пользовательского компаратора для использования в linq.join. Я не очень разбираюсь в linq, поэтому я, вероятно, неправильно понял поведение функции соединения.

Это мой код. Я хочу выполнить простое объединение между этими двумя списками:

List<MyObj> operand1Data = new List<MyObj>()
{
    new MyObj() { Var = "1var1", Year = 0 },
    new MyObj() { Var = "1var2", Year = 2018 },
};

List<MyObj> operand2Data = new List<MyObj>()
{
    new MyObj() { Var = "2var1", Year = 2018 },
    new MyObj() { Var = "2var2", Year = 2019 },
    new MyObj() { Var = "2var3", Year = 2020 },
};

var result= operand1Data.Join(operand2Data, x => x.Year, y => y.Year, (x, y) => x.Var + y.Var, new TestComparer()).ToList();

Проблема в том, что я хочу, чтобы 0 соответствовал каждому элементу в другом списке, поэтому я создал этот пользовательский компаратор:

public class TestComparer : IEqualityComparer<int>
{
    public bool Equals(int x, int y)
    {
        if (x == 0 || y == 0)
        {
            return true;
        }
        else
        {
            return x.Equals(y);
        }
    }

    public int GetHashCode(int obj)
    {
        return 1;
    }
}

Это не работает. Результат содержит только:

"1var12var3"
"1var22var1"

и то, что я ожидал, было:

"1var12var1"
"1var12var2"
"1var12var3"
"1var22var1"

Чего мне не хватает? Может кто-нибудь помочь мне исправить это? Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 08 октября 2019

Я попробовал ваш код, и я думаю, что LINQ Join имеет фильтр по умолчанию, который применяется перед пользовательским IEqualityComparer<T>.

С журналом внутри Equals(x,y), вот что я получил:

"Equality test x:2018 y:2019 = False"
"Equality test x:2019 y:2020 = False"
"Equality test x:2018 y:2020 = False"
"Equality test x:2020 y:0 = True"
"Equality test x:2020 y:2018 = False"
"Equality test x:2019 y:2018 = False"
"Equality test x:2018 y:2018 = True"

Видите? Только одна проверка на равенство «ноль».

Итак, я предлагаю использовать синтаксис запроса linq с перекрестным соединением, а затем фильтровать элементы по where условиям:

var result = from o1 in operand1Data
             from o2 in operand2Data
             where o1.Year == 0 || o2.Year == 0 || o1.Year == o2.Year
             select o1.Var + o2.Var;

. результат именно то, что вы ищете:

"1var12var1"
"1var12var2"
"1var12var3"
"1var22var1"

Надеюсь, это поможет!

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