11

我正在编写一些单元测试,但以下断言失败:

Assert.AreEqual(expected.Episode, actual.Episode);

如果我改为调用它,它会成功:

Assert.IsTrue(expected.Episode.Equals(actual.Episode));

在这种情况下,我假设Assert.AreEqual()最终会调用Equals()给定类型的方法Episode.Equals()

但是,在Microsoft.VisualStudio.TestTools.UnitTesting.Assert的幕后,我发现了以下代码(由 ReSharper 反编译):

public static void AreEqual<T>(T expected, T actual, string message, params object[] parameters)
{
    if (object.Equals((object)expected, (object)actual))
        return;
    Assert.HandleFail...
}

这对我来说意味着该AreEqual()方法正在强制使用基本方法expected而不是我在类中编写的重载。基本方法将简单地检查引用是否相同,而它们不是。actualobjectEquals()Episode

我有两个问题:

  1. 我的解释实际上是正确的,还是我错过了什么?
  2. 为什么框架要强制使用 object.Equals() 而不是该方法的重载?

如果它是相关的,这是我的方法:

public bool Equals(Episode other)
{
    return Number == other.Number &&
           CaseNote.Equals(other.CaseNote) &&
           Patient.Equals(other.Patient);
}
4

2 回答 2

6

它正在使用object.Equals(object,object),它处理以下内容:

  • 它们是相同的参考吗?
  • 是参考还是两者都是null参考?

然后处理完这些事情继续使用。它必须将它们投射到,因为这就是需要的。铸造 to也避免了一些并发症(因为一个盒子要么是常规的 boxed 要么是常规的 boxed )。x.Equals(y) object object.Equals(object,object)objectNullable<T>T?nullT

但是,它也可以实现为:

 if (EqualityComparer<T>.Default.Equals(expected,actual))
    return;

它处理Nullable<T>, IEquatable<T>, structvsclass和其他一些没有任何装箱的场景。

但是:当前的实现可以完成这项工作,偶尔的盒子并不是世界末日(并且:如果你的类型是 a ,装箱甚至不是问题class)。

于 2012-11-14T14:30:02.140 回答
4

在您的代码中,您还需要覆盖Equals(object other)(并且也需要覆盖 GetHashCode)。

只需将其添加到您的代码中

public bool Equals(Episode other)
{
    return Number == other.Number &&
           CaseNote.Equals(other.CaseNote) &&
           Patient.Equals(other.Patient);
}

public override bool Equals(object other)
{
    Episode castOther = other as Episode;
    if(castOther == null)
        return false;
    return this.Equals(castOther);
}

public override int GetHashCode()
{
    //TODO: Implement using the members you used in "Equals(Episode other)"
    throw new NotImplmentedExecption();
}

记住 GetHashCode 如果两个对象相等,它们也必须返回相等的哈希码。这是一个帮助可视化的快速图表。

在此处输入图像描述

您可能需要检查CaseNotePatient类似的问题。

于 2012-11-14T15:10:12.223 回答