2010-02-26 3 views
0

Рассмотрим этот массивIEqualityComparer означает

 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.I означает, как сравнение фактически делается ,
Каково значение ключа в IGrouping, почему он показывает 5 и 6?

+1

Вы можете достичь той же группировки, используя президенты. GroupBy (p => (p.Length> 5)); Конечно, это не отвечает на ваш вопрос, но это избавит вас от написания компаратора вообще. – Jens

ответ

2

Он показывает 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); 
    } 
} 
+0

Не могли бы вы предоставить мне пошаговое поведение кода. Я имею в виду, что сначала сканируется Adams, и это ключ найден ... что-то вроде этого или любой ссылки на него. Я просто не мог понять, как делается сравнение по Equals и GetHashCode. –

+0

Он уже дал такой хороший ответ;). – Younes

+0

@Akshay: Я бы выделил часть LINQ от IEqualityComparer - вы понимаете, с чем согласны равенства? –

Смежные вопросы