重写ToString()是否会导致自定义类的数值隐式相等比较失效?
断言失败原因
- 相等性实现不符合C#规范:你声明
Outer类实现了IEquatable<decimal>,但实际仅定义了接收Outer类型参数的Equals重载,既没有实现接口要求的Equals(decimal)方法,也没有重写object基类的Equals和GetHashCode方法。 - NUnit的
Assert.AreEqual比较两个引用类型时,默认调用object.Equals方法,该方法的默认逻辑是比较对象的引用地址。你代码中!a返回的是新创建的Outer实例,和b是两个独立对象,引用地址不同,哪怕Value值一致,默认比较也会失败。 - 额外语法问题:你定义的
!运算符存在错误,静态方法中不能直接访问实例字段Value,需要修改为1m - o.Value。
修复方案
按照C#相等性实现规范补全所有相关方法即可,修正后的代码如下:
public class Outer : IEquatable<Outer> { public decimal Value; public Outer(decimal val = 0.5m) => Value = val; public override string ToString() => $"Value: {Value}"; // 实现IEquatable<Outer>接口方法 public bool Equals(Outer other) { if (other is null) return false; return Value == other.Value; } // 重写object基类Equals方法 public override bool Equals(object obj) { return Equals(obj as Outer); } // 配套重写GetHashCode public override int GetHashCode() { return Value.GetHashCode(); } // 重载相等运算符 public static bool operator ==(Outer left, Outer right) { if (left is null) return right is null; return left.Equals(right); } public static bool operator !=(Outer left, Outer right) { return !(left == right); } public static implicit operator decimal(Outer o) => o.Value; public static implicit operator Outer(decimal d) => new Outer(d); // 修复逻辑非运算符错误 public static Outer operator !(Outer o) => new Outer(1m - o.Value); }
修改完成后,Assert.AreEqual(b, !a)就会按照Value值判断相等,正常通过测试。
内容的提问来源于stack exchange,提问作者Martin Bocanegra
相关产品推荐
相关产品推荐

