Значение IEqualityComparer - PullRequest
       12

Значение IEqualityComparer

0 голосов
/ 26 февраля 2010

Рассмотрим этот массив

        string[] presidents = {
            "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland",
            "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield",
            "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson",
            "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley",
            "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft",
            "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"};

Мой критерий группировки заключается в том, что имя длиной от 1 до 5 в одной группе и остальное в другой группе.
Я реализовал это с помощью этого производного класса

class MyLengthComparer:IEqualityComparer<Int32>
{
    public Int32 GetHashCode(Int32 i)
    {
        return i<=5?1:6;
    }


    public Boolean Equals(Int32 i1,Int32 i2)
    {
        if(i1<=5 && i2<=5)
            return true;
        if(i1>5 && i2>5)
            return true;
        else
            return false;
    }
}

Теперь я запускаю это

        IEnumerable<IGrouping<Int32, String>> groupVar = presidents.GroupBy(prez=>prez.Length,new MyLengthComparer());
        foreach(IGrouping<Int32, String> grp in groupVar)
        {
            Console.WriteLine("******" + grp.Key + "******" );
            foreach(String name in grp)
                Console.WriteLine(name);
        }

        Console.ReadKey();

Я хочу знать значение двух функций IEqualityInterface. Я имею в виду, как на самом деле выполняется сравнение.
Какое значение имеет ключ в IGrouping, почему он показывает 5 и 6?

1 Ответ

2 голосов
/ 26 февраля 2010

Показывает 5 и 6, потому что ключ группы считается ключом, созданным из первого элемента. «Адамс» имеет длину 5, «Артур» имеет длину 6, так что это ключи для группы.

Ключом для группы является то, что все в группе должно иметь общее. Ваш компаратор довольно странный в этом отношении.

По сути, каждый элемент в последовательности проецируется на ключ (длина имени), а затем выполняется поиск, чтобы выяснить, есть ли у этого ключа группа. Для этого поиска требуется хеш-код (так как это поиск на основе хеша) и равенство - и это то, что обеспечивает ваш пользовательский компаратор. Это дает хэш 1 или 6 в зависимости от длины (фактические числа относительно не важны; они согласуются с равенством, что означает, что поиск будет работать, и они отличаются, что означает, что он будет эффективным). Сама функция равенства на самом деле просто «являются ли эти значения одинаковыми в отношении того, что они меньше или равны 5». Я бы, наверное, реализовал это как:

public Boolean Equals(Int32 i1,Int32 i2)
{
    return (i1 <= 5) == (i2 <= 5);
}

Это на самом деле делает более очевидным, что вы получите те же группы (с другим ключом, по общему признанию), используя проекцию ключа x => x.Name.Length <= 5 и не предоставляя пользовательский компаратор:

var groups = presidents.GroupBy(prez => prez.Length <= 5);
foreach(var group in groups)
{
    // This time the key will be true or false
    Console.WriteLine("******" + group.Key + "******" );
    foreach(String name in group)
    {
        Console.WriteLine(name);
    }
}
...