我正在编写一些单元测试,但以下断言失败了:
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
和 actual
转换为 object
到强制使用基本 Equals()
方法,而不是我在 Episode
类中编写的重载。基本方法将简单地检查引用是否相同,如果它们不相同。
我有两个问题:
- 我的解释是否真的正确,还是我遗漏了什么?
- 为什么框架要强制使用 object.Equals() 而不是重载该方法?
如果相关,这是我的方法:
public bool Equals(Episode other)
{
return Number == other.Number &&
CaseNote.Equals(other.CaseNote) &&
Patient.Equals(other.Patient);
}
最佳答案
它正在使用 object.Equals(object,object)
,它处理类似的事情:
- 它们是同一个引用吗?
- 是一个或两个都是
null
引用?
then 在处理完这些事情后 继续使用 x.Equals(y)
。它必须将它们转换为 object
因为这是 object.Equals(object,object)
需要的。强制转换为 object
也避免了 Nullable<T>
的一些复杂情况(因为 T?
要么是 null
要么是常规的盒装 T
)。
但是,它也可以实现为:
if (EqualityComparer<T>.Default.Equals(expected,actual))
return;
它处理 Nullable<T>
、 IEquatable<T>
、 struct
与 class
以及其他一些没有任何装箱的场景。
但是:当前的实现可以完成这项工作,偶尔出现的框并不是世界末日(而且:如果您的类型是 class
,装箱甚至不是问题)。
关于c# - 为什么 Assert.AreEqual() 在比较之前转换为对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13380557/