Distinct()方法未调用equals方法

11

我已经实现了IEqualityComparer和IEquatable(都是为了确保),但是当我在集合上调用Distinct()方法时,它没有调用随之而来的方法。以下是在调用Distinct()时执行的代码。

ObservableCollection<GigViewModel> distinctGigs = new ObservableCollection<GigViewModel>(Gigs.Distinct<GigViewModel>());
return distinctGigs;
我想返回一个ObservableCollection,其中不包含在“Gigs” ObservableCollection 中的任何double对象。
我在GigViewModel类中实现接口如下:
public class GigViewModel : INotifyPropertyChanged, IEqualityComparer<GigViewModel>, IEquatable<GigViewModel>
{
    ....
}

然后重写接口中提供的方法,如下所示:

public bool Equals(GigViewModel x, GigViewModel y)
{          
    if (x.Artiest.Naam == y.Artiest.Naam)
    {
        return true;
    }
    else
    {
        return false;
    }
 }

 public int GetHashCode(GigViewModel obj)
 {
     return obj.Artiest.Naam.GetHashCode();
 }

 public bool Equals(GigViewModel other)
 {
     if (other.Artiest.Naam == this.Artiest.Naam)
     {
         return true;
     }
     else
     {
         return false;
     }
 }

非常感谢我得到的所有帮助。所以我创建了一个实现IEqualityComparer接口的独立类,并将它的实例传递到distinct方法中。但是这些方法仍然没有被触发。

EqualityComparer:

class GigViewModelComparer : IEqualityComparer<GigViewModel>
{
    public bool Equals(GigViewModel x, GigViewModel y)
    {

        if (x.Artiest.Naam == y.Artiest.Naam)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public int GetHashCode(GigViewModel obj)
    {
        return obj.Artiest.Naam.GetHashCode();
    }
}

Distinct()调用:

 GigViewModelComparer comp = new GigViewModelComparer();
 ObservableCollection<GigViewModel> distinctGigs = new ObservableCollection<GigViewModel>(Gigs.Distinct(comp));
 return distinctGigs;

编辑2:

GetHashCode()方法确实被调用了!在实现新类之后。但集合仍然包含重复项。我有一个包含'艺术家'(或Artist)对象的'演出'列表。这个艺术家有一个名为Naam的属性,它是一个字符串(名称)。


它调用了GetHashCode吗? - Liath
你确定这个方法没有被调用,还是只是在结果中看到了“重复项”?你确定这不是空格或字符大小写的差异吗? - D Stanley
我非常确定。我在方法中设置了断点,但它们没有被触发。而且结果中有重复项。 - Tim Kranen
2
哦,我的天啊,我真是太蠢了。我应该在GigViewModel对象上覆盖GetHashCode()方法!那样最终行得通了! - Tim Kranen
1
@CodesInChaos 我认为你应该留下一个答案,让我可以接受并声明我应该在GigViewModel中重写GetHashCode()方法。 - Tim Kranen
显示剩余6条评论
2个回答

9
所以,您让对象自己实现IEquatableIEqualityComparer两个接口。这通常是没有意义的。 IEquatable 是一种表明对象可以将自己与其他对象进行比较的方式。 IEqualityComparer 是一种表明它可以将您提供给它的两个不同的东西进行比较。 通常情况下,您只需要选择其中一个。
如果要实现IEquatable,则对象不仅需要具有适当签名的Equals方法,还需要重写GetHashCode以针对给定的相等定义具有合理的实现。您没有这样做。 您创建了一个带有对象参数的GetHashCode方法,但这是用于IEqualityComparer的重载。 当使用IEquatable时,您需要重写无参数版本(在Object中定义的版本)。
如果要创建一个实现IEqualityComparer的类,则需要将比较器传递给Distinct方法。由于您已将对象定义为其自身比较器,因此需要将此对象的某个实例作为第二个参数传递。当然,以这种方式传递并不真正有太多意义;因此,如果您采用这种方法,最好将与IEqualityComparer相关的两个方法提取到新类型中,并为该类型创建一个实例以用于Distinct方法。如果您实际上传递了具有这些定义的对象作为比较器,它将正常工作。

首先:感谢您的回复!我尝试了这个方法(请看我的编辑),但我仍然面临着同样的问题。 - Tim Kranen
@TimKranen Naam 的类型是什么? - Servy

1

根据MSDN的建议, 您最好为您的相等比较创建一个单独的类:

我们建议您从EqualityComparer类派生,而不是实现IEqualityComparer接口,因为EqualityComparer类使用IEquatable.Equals方法而不是Object.Equals方法进行相等性测试。这与Dictionary类和其他泛型集合的Contains、IndexOf、LastIndexOf和Remove方法一致。

因此,请创建一个名为GigViewModelComparer的类,该类派生自EqualityComparer并在其中放置您的EqualsGetHashCode方法。

然后,在调用Gigs.Distinct(new GigViewModelComparer())时传入该新比较器类的实例,它应该可以正常工作。请参考我上面提供的MSDN链接中的示例。

我从未见过有人在包含所讨论的集合类型的对象的同一类中实现IEqualityComparer,这可能至少是您问题的一部分原因。


1
那对他目前的问题没有帮助。 - Servy
确实,@Servy没有。不过:感谢您的贡献。 - Tim Kranen
@TimKranen 但是我的建议创建一个比较器类让你更进一步,现在你仍然看到重复的条目? - Sven Grosen
1
不再是这样了,错误在于GigViewModel没有重写GetHashCode()方法。 - Tim Kranen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接