等于、GetHashCode 和运算符覆盖在 IEquatable 实现中未调用



我正在尝试实现IEqueatable,所以我可以使用.除了在我的自定义类型 LINQ 查询中。

自定义类型代码如下所示:

public class Case : IEquatable<Case>
    {
        [Key]
        public int Id { get; set; }
        //More properties
        [...]      
        public bool Equals(Case other)
        {
            // Check whether the compared object references the same data.
            if (ReferenceEquals(this, other)) return true;
            // Check whether the compared object is null.
            if (ReferenceEquals(other, null)) return false;
            // Check whether the objects’ properties are equal.
            return Id.Equals(other.Id);
        }
        public override bool Equals(object obj)
        {
            var other = obj as Case;
            // Check whether the compared object references the same data.
            if (ReferenceEquals(this, other)) return true;
            // Check whether the compared object is null.
            if (ReferenceEquals(other, null)) return false;
            // Check whether the objects’ properties are equal.
            return Id.Equals(other.Id);
        }
        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }
        public static bool operator ==(Case case1, Case case2)
        {
            if ((object)case1 == null || (object)case2 == null)
                return Equals(case1, case2);
            return case1.Equals(case2);
        }
        public static bool operator !=(Case case1, Case case2)
        {
            if ((object)case1 == null || (object)case2 == null)
                return !Equals(case1, case2);
            return !case1.Equals(case2);
        }
    }

我在 Equals 方法中添加了throw new NotImplementedException();,但它从未被调用。

我遵循了此处显示的约定:https://msdn.microsoft.com/en-us/library/ms131190.aspx

和这里https://blogs.msdn.microsoft.com/csharpfaq/2009/03/25/how-to-use-linq-methods-to-compare-objects-of-custom-types/

但没有成功。

编辑

下面是调用 Except 方法的代码:

 if (Checkset(set))
                    {
                        var subset = GetPowerSet(set);
                        var newset = powerset.Except(subset);
                    }

其中powersetsubset都是Case数组。

在尝试使用 linq 查询执行操作之前,我建议使用更简单的方法。 即

var case1_1 = new Case() { Id = 1 };
var case1_2 = new Case() { Id = 1 };
var areEqual = case1_1 == case1_2;

有了这个测试,这些是我能想到为什么你没有达到那个异常的原因:

  1. 您有 2 个Equals方法,并且您只从其中 1 个中抛出了异常。
  2. 您比较的 2 个对象没有相同的Id。 如果GetHashCode的结果不同,它甚至可能不会尝试比较这些值。
  3. 捕获了异常
我很

想知道您是否尝试在两个重载中捕获Equals......从代码中弹出的唯一内容是,您有重复的实现来检查相等性。理想情况下,您只能在一个地方执行此操作。

下面是一个示例实现...您将EntityBase替换为Case...

  /// <summary>
  ///    Indicates whether the current object is equal to another object of the same type.
  /// </summary>
  /// <returns> true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false. </returns>
  /// <param name="other"> An object to compare with this object. </param>
  public bool Equals( EntityBase other ) {
     return !ReferenceEquals(other, null)
            && Id.Equals(other.Id);
  }
  /// <summary>
  ///    Serves as a hash function for a particular type.
  /// </summary>
  /// <returns> A hash code for the current <see cref="T:System.Object" />. </returns>
  /// <filterpriority> 2 </filterpriority>
  public override int GetHashCode() {
     return Id.GetHashCode();
  }
  /// <summary>
  ///    Determines whether the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />.
  /// </summary>
  /// <returns> true if the specified object is equal to the current object; otherwise, false. </returns>
  /// <param name="obj"> The object to compare with the current object. </param>
  /// <filterpriority> 2 </filterpriority>
  public override bool Equals( object obj ) {
     return Equals(obj as EntityBase);
  }
  /// <summary>
  ///    Determines if the <paramref name="left" /> instance is considered equal to the <paramref name="right" /> object.
  /// </summary>
  /// <param name="left"> The instance on the left of the equality operator. </param>
  /// <param name="right"> The instance on the right of the equality operator. </param>
  /// <returns> True if the instances are considered equal, otherwise false. </returns>
  public static bool operator ==( EntityBase left, EntityBase right ) {
     return ReferenceEquals(left, null)
        ? ReferenceEquals(right, null)
        : left.Equals(right);
  }
  /// <summary>
  ///    Determines if the <paramref name="left" /> instance is considered unequal to the <paramref name="right" /> object.
  /// </summary>
  /// <param name="left"> The instance on the left of the inequality operator. </param>
  /// <param name="right"> The instance on the right of the inequality operator. </param>
  /// <returns> True if the instances are considered unequal, otherwise false. </returns>
  public static bool operator !=( EntityBase left, EntityBase right ) {
     return !(left == right);
  }

如果您只调用 Except:

var exceptList = list1.Except(list2);

不返回任何列表,要执行比较,您需要枚举 Except 的结果,例如 foreach:

foreach(var listElement in exceptList) 
{
    //...
}

然后调用 GetHashCode 和 Equals 方法。

编辑:此代码执行两个列表的"除外":

    static void Main(string[] args)
    {
        List<MyClass> list1 = new List<MyClass>();
        MyClass myClass1 = new MyClass() {Id = 1};
        MyClass myClass2 = new MyClass() {Id = 2};
        list1.Add(myClass1);
        list1.Add(myClass2);
        List<MyClass> list2 = new List<MyClass>();
        list2.Add(myClass1);
        var exceptList = list1.Except(list2);
        foreach (var myClass in exceptList)
        {
            Console.WriteLine(myClass.Id);
        }
    }

    public class MyClass : IEquatable<MyClass>
    {
        public int Id { get; set; }
        public bool Equals(MyClass other)
        {
            return Id == other.Id;
        }
        public override int GetHashCode()
        {
            return Id;
        }
    }

此代码在控制台中打印"2">

Equals 只在必要时调用。处理IEquatable<T>实现的所有 LINQ 方法首先使用(并存储(它们处理的对象的哈希代码。仅当两个对象具有相同的哈希代码时,这些方法才调用Equals

在您的数据中,没有具有相同Id的情况,因此永远没有必要调用Equals

这可以通过一个例子轻松证明。如果您有三个列表:

var list1 = new List<Case>
{
    new Case{ Id = 1 },
    new Case{ Id = 2 },
    new Case{ Id = 3 }
};
var list2 = new List<Case>
{
    new Case{ Id = 4 },
    new Case{ Id = 5 },
    new Case{ Id = 6 }
};
var list3 = new List<Case>
{
    new Case{ Id = 1 },
    new Case{ Id = 5 },
    new Case{ Id = 6 }
};

然后下面的语句(在 EqualsGetHashCode 中有一些跟踪语句,后者只是返回 Id (...

list1.Except(list2).ToList();

。将输出:

GetHashCode: 4
GetHashCode: 5
GetHashCode: 6
GetHashCode: 1
GetHashCode: 2
GetHashCode: 3

虽然声明...

list1.Except(list3).ToList();

。将输出:

GetHashCode: 1
GetHashCode: 5
GetHashCode: 6
GetHashCode: 1
Equals: 1 - 1
GetHashCode: 2
GetHashCode: 3

相关内容

  • 没有找到相关文章

最新更新