【问题标题】:IEquatable, how to implement this properly [duplicate]IEquatable,如何正确实施[重复]
【发布时间】:2012-01-09 11:03:50
【问题描述】:

我正在使用 .net 2.0 和 c#,并且我已经在我的类中实现了 IEquatible 接口,如下所示:-

public MyClass() :  IEquatable<MyClass>
{
    Guid m_id = Guid.NewGuid();

    public Guid Id
    {
        get
        {
            return m_id;
        }
    }

    #region IEquatable<MyClass> Members

    public bool Equals(MyClass other)
    {
        if (this.Id == other.Id)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    #endregion
}

这是不好的编程习惯吗?我读过我还需要实现 Object.Equals 和 Object.GetHashCode ,但我不知道为什么。

我希望能够检查 MyClass 的实例是否尚未包含在 MyClass 类型的通用列表中。为什么框架只建议你只实现 Equals?

任何帮助将不胜感激。

【问题讨论】:

  • 实现可以简写为:return this.Id == other.Id;.
  • 你想达到什么目的?使用上面发布的代码,MyClass 的每个实例都将使用新的 Guid 进行初始化,这意味着每个实例都是唯一的并且不能等同于另一个实例,这是期望的行为吗?
  • 我同意。如果每个实例都有一个唯一的 ID,那么 Object.ReferenceEquals 将以相同的方式工作(除非有可能克隆 MyClass 的实例)。
  • @AmarPalsapure - 与 OP 发布的代码将产生的 NullReferenceException 相同。

标签: c# .net c#-2.0


【解决方案1】:

您可以使用 LINQ 使用自定义谓词来检查您的列表是否包含某个项目。在这种情况下,您不需要覆盖Equals 也不需要实现IEquatable

// check if the list contains an item with a specific ID
bool found = someList.Any(item => item.ID == someId);

如果您需要将项目存储在DictionaryHashtable 中,则覆盖Equals(使用GetHashCode)并实现IEquatable 很有用。

【讨论】:

    【解决方案2】:

    这是不好的编程习惯吗?

    实现IEquatable&lt;T&gt; 很棒,对于结构体更是如此,但仅仅做这么多是不够的。

    我读到我还需要实现 Object.Equals

    Read it here why..

    还有 Object.GetHashCode,但我不知道为什么。

    Read it herehere。说真的,这些已经讨论过很多次了,而且很简单。简而言之,您需要它来处理像 Dictionary&lt;,&gt;HashSet&lt;&gt; 这样的哈希值的集合类型

    我希望能够检查 MyClass 的实例是否尚未包含在 MyClass 类型的通用列表中。为什么框架只建议你只实现 Equals?

    取决于集合类型。对于List&lt;T&gt;,它将仅根据您定义Equals 方法的方式检查相等性,例如Contains 方法。对于大多数情况,您只需要Equals。但是如果你有一个HashSet&lt;T&gt;,那么缺席和存在检查将利用你的对象的哈希值。框架确实要求我们实现良好的散列方法(无需重新发明轮子)at appropriate places

    任何帮助将不胜感激。

    如下所示,但您必须重载运算符 ==!=,前提是它对您有意义。看到您的课程,我认为可以为您的课程提供价值语义。否则,只需忽略该部分(如果 == 应该意味着引用相等)...从您的 guid 获取哈希码就足够了,前提是您需要测试相等性。

    public sealed class MyClass : IEquatable<MyClass>
    {
        Guid m_id = Guid.NewGuid();
    
        public Guid Id { get { return m_id; } }
    
        public bool Equals(MyClass other)
        {
            if (ReferenceEquals(this, other))
                return true;
    
            if (ReferenceEquals(null, other))
                return false;
    
            return Id == other.Id; 
        }
    
        public override bool Equals(object obj)
        {
            return Equals(obj as MyClass);
        }
    
        public static bool operator ==(MyClass lhs, MyClass rhs)
        {
            if (ReferenceEquals(lhs, null))
                return ReferenceEquals(rhs, null);
    
            return lhs.Equals(rhs);
        }
    
        public static bool operator !=(MyClass lhs, MyClass rhs)
        {
            return !(lhs == rhs);
        }
    
        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }   
    }
    

    为避免误会,请使用可用的 sn-p here 以获得良好的概述 see this SO thread.

    【讨论】:

      猜你喜欢
      • 2012-02-19
      • 1970-01-01
      • 2021-12-12
      • 2019-02-01
      • 1970-01-01
      • 2022-12-22
      • 2020-11-22
      • 2010-11-16
      • 2022-01-08
      相关资源
      最近更新 更多