从HashSet中获取不同的值

本文关键字:获取 HashSet | 更新日期: 2023-09-27 18:05:17

我只想从HashSet中获得不同的值,我已经实现了IEquatable, IEqualityComparer,但仍然无法获得不同的值。

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

谢谢!

从HashSet中获取不同的值

如果您只有一个实现来定义类的相等性,那么实现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);
}

public override bool = (您不需要在HashSet<T>上调用Distinct(),因为它本身保证了其内部集合的唯一性,只要您提供适当的IEquatable<T>覆盖或为其提供IEqualityComparer<T>

来自HashSet<T>.Add的文档:

返回值:

类型:系统。对象中添加该元素时为Boolean值HashSet对象;如果元素已经存在,则为False。

首先,您应该将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>实现来覆盖许多用例,这些用例可以为同一对象定义不同的唯一性含义(即Item)。

如果你提供了一个很好的IEqualityComparer<T>实现,你将不需要Distinct,因为HashSet<T>是一个集合,这意味着它是一个无序的唯一元素集合,整个集合将使用相等比较器来检查给定元素是否存在于集合中(因此,所有元素在同一个集合中都是唯一的!)。