2015-07-29 17 views
0

Я хочу получить только отличные от HashSet, я реализовал IEquatable, IEqualityComparer, но все еще не могу получить отличные значения. ВыходПолучите отличные от HashSet

class Program 
{ 
    static void Main(string[] args) 
    { 

     HashSet<Item> items = new HashSet<Item>() 
     { 
      {new Item("item1")}, 
      {new Item("item2")}, 
      {new Item("item3")}, 
      {new Item("item1")} 
     }; 

     foreach (var item in items.Distinct()) 
     { 
      Console.WriteLine(item.Name); 
     } 

     Console.ReadKey(); 

    } 
} 


class Item : IEquatable<Item>, IEqualityComparer<Item> 
{ 
    public string Name { get; set; } 
    public Item(string name) 
    { 
     this.Name = name; 
    } 

    public bool Equals(Item other) 
    { 
     return this.Name.Equals(other.Name); 
    } 

    public bool Equals(Item x, Item y) 
    { 
     return x.Equals(y); 
    } 

    public int GetHashCode(Item obj) 
    { 
     return this.Name.GetHashCode(); 
    } 
} 

консоли:

item1 
item2 
item3 
item1 

Спасибо!

ответ

2

Прежде всего, вы должны реализовать IEqualityComparer<T> как отдельный класс, и вам необходимо предоставить весь компаратор равенство во HashSet<T> строительства:

var set = new HashSet<CustomClass>(new CustomClassEqualityComparer()); 

Если вы идете с равенством компаратор образом, вы Арен» т вынуждены осуществлять IEquatable<T>:

public class ItemEqualityComparer : IEqualityComparer<Item> 
{ 
    public bool Equals(Item x, Item y) 
    { 
     return x.Name == y.Name; 
    } 

    public int GetHashCode(Item obj) 
    { 
     return obj.Name.GetHashCode(); 
    } 
} 

Кроме того, вы можете создать множество IEqualityComparer<T> реализаций, чтобы покрыть много нас e случаях, которые могут определять различные значения уникальности для одного и того же объекта (т. Item).

Если вы обеспечить хорошую реализацию IEqualityComparer<T>, вам не нужно будет Distinct поскольку HashSet<T> является набором и это означает, что это неупорядоченная коллекция уникальных элементов, и все набор будет использовать равенство компаратор чтобы проверить, присутствует ли данный элемент в наборе (таким образом, все элементы уникальны в том же наборе !).

3

Если у вас есть только одна реализация, которая определяет равенство вашего класса, достаточно реализовать IEquatable<T> (правильно). Вы также не должны реализовывать IEqualityComparer<T>. Последнее подразумевается, как правило, как в отдельном классе, когда вы хотите предоставить несколько способов определения уникальности между двумя элементами типа.

Кроме этого, ваша подпись метода для GetHashCode неверна. В настоящее время он отказывается от object.Equals вместо вашей пользовательской реализации.

Вы должны добавить override ключевое слово в GetHashCode реализации и удалить Item obj из подписи:

public override int GetHashCode() 
{ 
    return this.Name.GetHashCode(); 
} 

А также переопределить object.Equals, а также использовать Equals(item other):

public override bool Equals(object obj) 
{ 
    if (ReferenceEquals(null, obj)) return false; 
    if (ReferenceEquals(this, obj)) return true; 
    if (obj.GetType() != this.GetType()) return false; 
    return Equals((Item) obj); 
} 

общественного переопределение bool Equals ( ) Вам не нужно звонить Distinct() на номер HashSet<T>, так как он сам гарантирует u в своей внутренней коллекции, при условии, что вы обеспечиваете надлежащее IEquatable<T> переопределение или поставку его IEqualityComparer<T>.

From the docs of HashSet<T>.Add:

Возвращаемое значение:

Тип: System.Boolean верно, если элемент добавляется к объекту HashSet; false, если элемент уже присутствует.

+0

Что касается «Equals (arg1, arg2)), им нужно« переопределить »ключевое слово? –

+0

@ MatjažMav No. Вам не нужно «Equals (arg1, arg2)» вообще. Вы в порядке с реализацией 'IEquatable ', не нужно для 'IEqualityComparer '. –

+0

C# автоматически добавил эти два метода в мой код. –

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