In C#, what's the difference between
Assert.AreNotEqual
and
Assert.AreNotSame
Almost all the answers given here are correct, but it's probably worth giving an example:
public static string GetSecondWord(string text)
{
// Yes, an appalling implementation...
return text.Split(' ')[1];
}
string expected = "world";
string actual = GetSecondWord("hello world");
// Good: the two strings should be *equal* as they have the same contents
Assert.AreEqual(expected, actual);
// Bad: the two string *references* won't be the same
Assert.AreSame(expected, actual);
AreNotEqual
and AreNotSame
are just inversions of AreEqual
and AreSame
of course.
EDIT: A rebuttal to the currently accepted answer...
If you use Assert.AreSame
with value types, they are boxed. In other words, it's equivalent to doing:
int firstNumber = 1;
int secondNumber = 1;
object boxedFirstNumber = firstNumber;
object boxedSecondNumber = secondNumber;
// There are overloads for AreEqual for various value types
// (assuming NUnit here)
Assert.AreEqual(firstNumber, secondNumber);
// ... but not for AreSame, as it's not intended for use with value types
Assert.AreSame(boxedFirstNumber, boxedSecondNumber);
Neither firstNumber
nor secondNumber
has an object value, because int
is a value type. The reason the AreSame
call will fail is because in .NET, boxing a value creates a new box each time. (In Java it sometimes doesn't - this has caught me out before.)
Basically you should never use AreSame
when comparing value types. When you're comparing reference types, use AreSame
if you want to check for identical references; use AreEqual
to check for equivalence under Equals
. EDIT: Note that there are situations where NUnit doesn't just use Equals
directly; it has built-in support for collections, where the elements in the collections are tested for equality.
The claim in the answer that:
Using the example above changing the int to string, AreSame and AreEqual will return the same value.
entirely depends on how the variables are initialized. If they use string literals, then yes, interning will take care of that. If, however, you use:
string firstString = 1.ToString();
string secondString = 1.ToString();
then AreSame
and AreEqual
will almost certainly not return the same value.
As for:
The general rule of thumb is to use AreEqual on value types and AreSame on reference types.
I almost never want to check for reference identity. It's rarely useful to me. I want to check for equivalence which is what AreEqual
checks for. (I'm not saying that AreSame
shouldn't be there - it's a useful method, just far more rarely than AreEqual
.)