未调用 C#GetHashCode/Equals 覆盖
Posted
技术标签:
【中文标题】未调用 C#GetHashCode/Equals 覆盖【英文标题】:C# GetHashCode/Equals override not called 【发布时间】:2010-11-06 22:42:14 【问题描述】:我遇到了 GetHashCode 和 Equals 的问题,我已经为一个类覆盖了这些问题。我正在使用运算符 == 来验证两者是否相等,如果它们的哈希码相同,我希望这将调用 GetHashCode 和 Equals 以验证它们确实相等。
但令我惊讶的是,两者都没有被调用并且相等测试的结果是错误的(虽然它实际上应该是真的)。
覆盖代码:
public class User : ActiveRecordBase<User>
[...]
public override int GetHashCode()
return Id;
public override bool Equals(object obj)
User user = (User)obj;
if (user == null)
return false;
return user.Id == Id;
平等检查:
if (x == y) // x and y are both of the same User class
// I'd expect this test to call both GetHashCode and Equals
【问题讨论】:
如果==
确实调用了您的Equals
方法,那么它会导致堆栈溢出,因为它在对象上使用==
运算符...
您显示的代码中没有任何内容表明需要调用 GetHashCode()。仅当您将对象用作集合的键时才会调用它。
【参考方案1】:
运营商==
与.GetHashCode()
或.Equals()
完全分离。
您可能对 Microsoft Guidelines for Overloading Equals() and Operator == 感兴趣。
简短的版本是:使用.Equals()
实现平等比较。使用运算符 ==
进行 identity 比较,或者如果您正在创建不可变类型(其中每个相等的实例都可以被认为是有效相同的)。此外,.Equals()
是一个虚方法,可以被子类覆盖,但运算符 ==
取决于使用它的表达式的编译时类型。
最后,为了保持一致,在您实施.Equals()
的任何时候实施.GetHashCode()
。重载运算符 !=
任何时候重载运算符 ==
。
【讨论】:
我的对象是可变的。我预计调用 == 运算符实际上会调用 Equals 方法,我以前见过该方法,但我不明白为什么它现在不起作用,而它以前起作用...... @tomzx:==
运算符永远不会调用 .Equals()
方法,除非您重载它这样做。
@Daniel 您对“==”的建议不正确。微软一贯表示,如果要进行 IDENTITY 比较,则必须使用“ReferenceEquals”。例如,考虑字符串。如果您使用字符串生成器生成两个具有相同 CONTENTS 但不同 ADDRESSES 的字符串,则“==”将返回 TRUE(相等比较),但 ReferenceEquals 将返回 FALSE。 "==" 通常被认为是一个 EQUALITY 比较,并且通常被实现为执行一个类的 EQUALS 所做的任何事情。
简单测试:ReferenceEquals(new String("abc"), new String("abc")) 返回 false。但是 ((new String("abc")) == (new String("abc"))) 返回 true。 THEREFORE "==" 是 EQUALITY 比较,而不是 IDENTITY 比较。碰巧的情况是,如果一个类没有指定“==”做什么,则默认行为是使用 ReferenceEquals。还要考虑 VALUE 对象,它显然对“==”进行了相等性测试。
@ToolmakerSteve:来自我回答中的链接:“当类型不可变时,即实例中包含的数据无法更改,重载运算符 == 来比较值相等而不是引用相等可能很有用,因为作为不可变对象,只要它们具有相同的值,它们就可以被认为是相同的。在非不可变类型中覆盖 operator == 不是一个好主意。 -- 这对我来说意味着 == 应该只在相等和身份可以安全混合的地方表现得像一个相等运算符(即,与不可变的值类型类似的值)。【参考方案2】:
也许在你的User
类中再添加一个方法。
public virtual bool Equals(User other)
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return other.Id == Id;
【讨论】:
你不是说override
而不是virtual
吗?以上是关于未调用 C#GetHashCode/Equals 覆盖的主要内容,如果未能解决你的问题,请参考以下文章
未调用 didEnterRegion 但在目标 C 中调用了 didExitRegion
致命错误:未捕获的错误:调用 C:\xampp\htdocs\ 中未定义的函数 mysql_connect()