【问题标题】:How to override Contains property of a list in C#?如何覆盖 C# 中列表的包含属性?
【发布时间】:2016-07-11 21:23:51
【问题描述】:

我有一个对象 List<IReportRelationMapping> 的列表,我需要检查该列表是否不包含特定的 ReportRelationMapping 对象

这是我的ReportRelationMapping 的样子

public class ReportRelationMapping : IReportRelationMapping
{
     public string Name { get; set; }

     public IReportRelation LocalRelation { get; set; }

     public IReportRelation ForeignRelation { get; set; }

     public IReportRelationMapping RelatedThrough { get; set; }
}

列表包含一个对象 if this.LocalRelation == passed.LocalRelation && this.ForeignRelation == passed.ForeignRelationthis.LocalRelation == passed.ForeignRelation && this.ForeignRelation == passed.LocalRelation

这是我为覆盖列表的Contains 属性所做的操作

public class ReportRelationMapping : IReportRelationMapping
{
    public string Name { get; set; }

    public IReportRelation LocalRelation { get; set; }

    public IReportRelation ForeignRelation { get; set; }

    public IReportRelationMapping RelatedThrough { get; set; }

    public bool Equals(ReportRelationMapping other)
    {
        if (other == null)
        {
            return false;
        }

        if (object.ReferenceEquals(this, other))
        {
            return true;
        }

        if (this.GetType() != other.GetType())
        {
            return false;
        }

        return (this.LocalRelation == other.LocalRelation && this.ForeignRelation == other.ForeignRelation)
            || (this.LocalRelation == other.ForeignRelation && this.ForeignRelation == other.LocalRelation);
    }

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

        if (object.ReferenceEquals(this, other))
        {
            return true;
        }

        if (this.GetType() != other.GetType())
        {
            return false;
        }

        return this.Equals(other as ReportRelationMapping);
    }

    public override int GetHashCode()
    {
        int hash = 14;
        hash = (hash * 7) + this.ForeignRelation.GetHashCode();
        return (hash * 7) + this.LocalRelation.GetHashCode();
    }

    public static bool operator ==(ReportRelationMapping lhs, ReportRelationMapping rhs)
    {
        // Check for null on left side. 
        if (Object.ReferenceEquals(lhs, null))
        {
            if (Object.ReferenceEquals(rhs, null))
            {
                // null == null = true. 
                return true;
            }

            // Only the left side is null. 
            return false;
        }
        // Equals handles case of null on right side. 
        return lhs.Equals(rhs);
    }

    public static bool operator !=(ReportRelationMapping lhs, ReportRelationMapping rhs)
    {
        return !(lhs == rhs);
    }

}

但由于某种原因,即使列表包含给定对象,我也会得到false 或“不包含该对象”。当我调试我的代码时,我可以看到调试器到达Equal 方法,所以它通过我的代码,但它永远不会到达GetHashCode 方法。我不确定我是否在这里错误地实现了我的GetHashCode 方法。

我在这里错过了什么?在我的情况下,为什么包含总是返回“不包含”? 如何正确覆盖列表的 Contains 方法?

【问题讨论】:

  • 好吧,您的哈希码与 Equals 不匹配,因为它应该为两个相等的对象返回相同的东西。哈希应该更像return this.ForeignRelation.GetHashCode() + this.LocalRelation.GetHashCode();

标签: c# list overriding contains gethashcode


【解决方案1】:

您可能应该通过调用Enumerable.Any() 来执行此操作,如下所示:

bool contains = myList.Any(t =>
    (t.LocalRelation == passed.LocalRelation && t.ForeignRelation == passed.ForeignRelation)
    || (t.LocalRelation == passed.ForeignRelation && t.ForeignRelation == passed.LocalRelation)

无需覆盖Equals 或任何其他内容。

或者,如果您不想使用 Enumerable (LINQ),可以使用 List.Exists 方法,您可以以相同的方式调用:

bool contains = myList.Exists(t =>
    (t.LocalRelation == passed.LocalRelation && t.ForeignRelation == passed.ForeignRelation)
    || (t.LocalRelation == passed.ForeignRelation && t.ForeignRelation == passed.LocalRelation)

【讨论】:

  • 这仍然给了我相同的结果。即使存在也总是不存在
  • @Jaylen:还有一些事情你没有告诉我们。您需要向我们提供一个我们可以测试的具体示例。也许你应该减少你的对象尽可能简单,这样你就不会用代码杀死我们。详情请见stackoverflow.com/help/mcve
  • 其实我告诉过你真实的故事,但出于某种原因.Any() 从第一次尝试就对我不起作用。现在它做到了。我想我错过了什么。非常感谢您对此的帮助。是否有理由选择一种方式而不是另一种方式?他们是一样的吗?
  • @Jaylen:Enumerable.Any() 的好处在于它可以与任何实现 IEnumerable<T> 的类一起使用,其中包括 System.Collections.Generic 命名空间中的所有集合,以及数组和人们创建的大多数支持 LINQ 的自定义集合。 List.Exists 仅适用于 LIst<T>。如果List.Exists() 不使用枚举器可能会更快,因此如果您的应用程序对性能非常敏感,您需要检查一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 1970-01-01
  • 2020-03-30
  • 2021-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多