简体   繁体   English

从HashSet获取不同的值

[英]Get distinct values from HashSet

I want to get only distinct values from HashSet , I have implemented IEquatable , IEqualityComparer , but still can't get distinct values. 我只想从HashSet获取不同的值,我已经实现了IEquatableIEqualityComparer ,但仍然无法获取不同的值。

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();
    }
}

Console output: 控制台输出:

item1
item2
item3
item1

Thanks! 谢谢!

If you only have a single implementation which defines equality of your class, implementing IEquatable<T> (properly) is enough. 如果只有一个实现定义类的相等性,则(适当地)实现IEquatable<T>就足够了。 You shouldn't implement IEqualityComparer<T> as well. 您也不应实现IEqualityComparer<T> The latter is meant to be, usually as in a separate class, when you want to provide multiple ways to define uniqueness between two elements of a type. 当您想提供多种方法来定义类型的两个元素之间的唯一性时,后者通常意味着与单独的类一样。

Other than that, Your method signature for GetHashCode is wrong. 除此之外,您对GetHashCode方法签名是错误的。 Currently, it defers to object.Equals instead of your custom implementation. 当前,它顺应object.Equals而不是您的自定义实现。

You need to add the override keyword to your GetHashCode implementation and remove the Item obj from the signature: 您需要将override关键字添加到您的GetHashCode实现中,并从签名中删除Item obj

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

And also override object.Equals as well to use your Equals(item other) : 并且重写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);
}

public override bool Equals( You don't need to call Distinct() on a HashSet<T> as it by itself guarantees uniqueness in its internal collection, given that you provide a proper IEquatable<T> override or supply it with an IEqualityComparer<T> . 公共重写bool Equals(您无需在HashSet<T>上调用Distinct() ,因为它提供了适当的IEquatable<T>重写或为其提供了IEqualityComparer<T>

From the docs of HashSet<T>.Add : HashSet<T>.Add的文档中

Return Value: 返回值:

Type: System.Boolean true if the element is added to the HashSet object; 类型:System.Boolean如果将元素添加到HashSet对象,则为true;否则为false。 false if the element is already present. 如果该元素已经存在,则返回false。

First of all, you should implement IEqualityComparer<T> as a separate class and you need to provide the whole equality comparer during HashSet<T> construction: 首先,您应该将IEqualityComparer<T>作为一个单独的类实现,并且需要在HashSet<T>构造过程中提供整个相等比较器:

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

If you go with the equality comparer way, you aren't forced to implement IEquatable<T> : 如果采用相等比较器方式,则不必强制实现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();
    }
}

Furthermore, you can design many IEqualityComparer<T> implementations to cover many use cases that can define different uniqueness meanings to the same object (ie Item ). 此外,您可以设计许多IEqualityComparer<T>实现,以涵盖许多用例,这些用例可以为同一对象(即Item )定义不同的唯一性含义。

If you provide a good implementation of IEqualityComparer<T> , you won't need Distinct since a HashSet<T> is a set and this means that it's an unordered collection of unique elements, and the whole set will use your equality comparer to check if a given element is present in the set (thus, all elements are unique in the same set !). 如果您提供了IEqualityComparer<T>的良好实现,那么您将不需要Distinct因为HashSet<T>是一个集合 ,这意味着它是唯一元素的无序集合,并且整个集合将使用相等比较器进行检查如果给定的元素存在于该 (因此,所有的元素都在同一唯一!)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM