C# Equals、GetHashCode和运算符重写在IEquatable实现中未调用的内容
我正在尝试实现IEqueatable,以便可以使用。自定义类型LINQ查询除外 自定义类型代码如下所示:C# Equals、GetHashCode和运算符重写在IEquatable实现中未调用的内容,c#,linq,equals,iequalitycomparer,iequatable,C#,Linq,Equals,Iequalitycomparer,Iequatable,我正在尝试实现IEqueatable,以便可以使用。自定义类型LINQ查询除外 自定义类型代码如下所示: public class Case : IEquatable<Case> { [Key] public int Id { get; set; } //More properties [...] public bool Equals(Case other) {
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);
}
}
powerset和subset都是Case数组。在尝试使用linq查询之前,我建议使用更简单的方法。即
var case1_1 = new Case() { Id = 1 };
var case1_2 = new Case() { Id = 1 };
var areEqual = case1_1 == case1_2;
有了这个测试,我可以想到为什么你没有遇到这个异常:
您有2个Equals方法,并且只从其中1个抛出了异常。
您所比较的两个对象没有相同的Id。如果GetHashCode的结果不同,它甚至可能不会尝试比较这些值。
异常被捕获
我很想知道你是否尝试过在两个重载中陷进相等的内容。。。从代码中弹出的唯一一件事是,您有用于检查相等性的重复实现。理想情况下,你只能在一个地方这样做 下面是一个示例实现。。。您将用Case替换EntityBase
如果您只打电话,除了:
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实现的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 }
};
。。。将输出:
GetHashCode: 4
GetHashCode: 5
GetHashCode: 6
GetHashCode: 1
GetHashCode: 2
GetHashCode: 3
GetHashCode: 1
GetHashCode: 5
GetHashCode: 6
GetHashCode: 1
Equals: 1 - 1
GetHashCode: 2
GetHashCode: 3
虽然声明
list1.Except(list3).ToList();
。。。将输出:
GetHashCode: 4
GetHashCode: 5
GetHashCode: 6
GetHashCode: 1
GetHashCode: 2
GetHashCode: 3
GetHashCode: 1
GetHashCode: 5
GetHashCode: 6
GetHashCode: 1
Equals: 1 - 1
GetHashCode: 2
GetHashCode: 3
你能在需要调用Equals的地方添加Linq代码吗?你的测试用例有两个Id相同的用例吗?@RubenAguilar添加了代码@PetSerAl否,案例将只有一个唯一Id。使用惰性评估除外。您是否列举了newset?您好,发生的情况是,exceptList根本不起作用,因此在本例中exceptList的值将与list1相同。感谢您发布此消息,但我已经尝试过这种方式,但行为仍然相同。我知道子集中的对象在旧列表中,因为它是旧列表对象之一的powerset。电源集是一个集合,包含集合中所有可能的项目组合。因此,旧集是X项的前一个功率集,而新集是旧集的一个功率集,这意味着所有这些项都在旧列表中,因此,在我的BL中,它们需要删除。嗨,谢谢你的回答。我做了多个测试和测试:1。首先,拥有2个equals方法是实现IEqueatble的方式,一个覆盖类的前一个签名,另一个使用类型Case指定自定义比较。这在我作为参考提供的MSDN链接中有建议。永远不会抛出异常。2.我还在GetHashCode中添加了throw新异常,该异常未被计算。我知道事实上我正在比较的案例是匹配的。3.没有发现异常。@RainierMallol我并不是说你不应该有2个equals方法。我只是说您可能签入了错误的方法。谢谢,但是GetHashCode方法也从来没有被调用过。在我的例子中是这样的。您应该提供更多关于测试用例中数据的详细信息,以及如何确定未调用GetHashCode。嗨,Peter John,谢谢您的消息。您的代码缺少IQuetable.EqualEntityBase的实现。我已经将它添加到我的代码中,但仍然得到相同的结果。
GetHashCode: 1
GetHashCode: 5
GetHashCode: 6
GetHashCode: 1
Equals: 1 - 1
GetHashCode: 2
GetHashCode: 3