Distinct()返回具有用户定义类型的重复项

Tha*_*Guy 7 c# linq

我正在尝试编写一个Linq查询,该查询返回一个对象数组,其构造函数中包含唯一值.对于整数类型,Distinct只返回每个值的一个副本,但是当我尝试创建对象列表时,事情就会崩溃.我怀疑这是我的类的相等运算符的问题,但是当我设置断点时,它从未被击中.

过滤掉子表达式中的重复int可以解决问题,并且还可以避免构造将立即丢弃的对象,但我很好奇为什么这个版本不起作用.

更新:晚上11:04 有几个人指出MyType不会覆盖GetHashCode().我担心这个例子过于简单了.原始的MyType确实实现了它.我在下面添加了它,仅修改为在返回它之前将哈希代码放入临时变量中.

通过调试器运行,我看到GetHashCode的所有五次调用都返回不同的值.由于MyType只继承自Object,因此可能与Object所表现的相同.

我是否正确,然后得出结论,哈希应该基于值的内容?这是我第一次尝试覆盖运营商,当时看起来GetHashCode似乎并不特别花哨.(这是我的第一次平等检查似乎没有正常工作.)

class Program
{
    static void Main(string[] args)
    {
        int[] list = { 1, 3, 4, 4, 5 };
        int[] list2 =
            (from value in list
             select value).Distinct().ToArray();    // One copy of each value.
        MyType[] distinct =
            (from value in list
             select new MyType(value)).Distinct().ToArray(); // Two objects created with 4.

        Array.ForEach(distinct, value => Console.WriteLine(value));
    }
}

class MyType
{
    public int Value { get; private set; }

    public MyType(int arg)
    {
        Value = arg;
    }

    public override int GetHashCode()
    {
        int retval = base.GetHashCode();
        return retval;
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        MyType rhs = obj as MyType;
        if ((Object)rhs == null)
            return false;

        return this == rhs;
    }

    public static bool operator ==(MyType lhs, MyType rhs)
    {
        bool result;

        if ((Object)lhs != null && (Object)rhs != null)
            result = lhs.Value == rhs.Value;
        else
            result = (Object)lhs == (Object)rhs;

        return result;
    }

    public static bool operator !=(MyType lhs, MyType rhs)
    {
        return !(lhs == rhs);
    }
}
Run Code Online (Sandbox Code Playgroud)

dth*_*rpe 8

您需要在类中重写GetHashCode().GetHashCode必须与Equals重载一起实现.代码在调用Equals之前检查哈希码是否相等是很常见的.这就是为什么你的Equals实现没有被调用.

  • `Distinct`使用`Set <T>`来跟踪之前看过的项目,并且`Set <T>`在内部使用`GetHashCode()`. (3认同)
  • 改写.关键是,原始海报注意到他的Equals实现根本没有被调用.原因?执行相等比较的系统(默认相等比较器,无论如何)在调用Equals之前检查哈希码.他没有覆盖GetHashCode,所以哈希值永远不会相同,所以他的Equals实现永远不会被调用.如果他修复了GetHashCode()问题,那么他可能会自己弄清楚他的Equals实现中也存在错误. (2认同)