0

How can my strings have different hash codes but the same text value of "16 777 216"?

The test method does not pass:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestStringEquals
{
  [TestClass]
  public class FormatterTests
  {
    [TestMethod]
    public void Double_Test_1()
    {
      Assert.AreEqual("16 777 216", FormatDoubleWithThousandSeparator(16777216, 0));
    }

    public string FormatDoubleWithThousandSeparator(double value, int digits)
    {
      double result = Math.Round((double)value, digits);

      System.Globalization.NumberFormatInfo nfi = (System.Globalization.NumberFormatInfo)System.Globalization.NumberFormatInfo.InvariantInfo.Clone();
      nfi.NumberGroupSeparator = " ";

      return result.ToString("###,###,###,###,###,###,##0.#####", nfi);
    }
  }
}

4 Answers4

4

Maybe the test output is more helpful if you replace your assertion with:

Assert.AreEqual("16 777 216", numberToString);
Dennis Traub
  • 50,557
  • 7
  • 93
  • 108
3

I ran that unit test in Visual Studio 2010, and it did pass for me. It may have to do with some culture setting on your computer, or possibly how the == operator behaves on strings.

edited for clarity

CD Jorgensen
  • 1,361
  • 9
  • 8
2

Assert.IsTrue() accepts two Object type arguments. The == operator for object types checks reference equality. Strings overload the == operator to instead check for value equality, but when you pass the strings to that function you have effectively cast them as objects and forced it to use object's == operator: it's going to check your strings for reference equality, which may or may not return true depending on whether the strings are interned.

Instead, use Assert.AreEqual() or
Assert.IsTrue("16 777 216".Equals(numberToString), "Expected 2^24").

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
0

Because the two strings are not the same object, thus they are not equal, there is a string comparision method that should be used instead.

Make sure this isn't the case one string has a non-printing character and the other one does not. You have to remember that a string is an object. So you need to compare the value of said object to the value of another object.

http://msdn.microsoft.com/en-us/library/system.string.equals.aspx
http://msdn.microsoft.com/en-us/library/1hkt4325.aspx

Security Hound
  • 2,577
  • 3
  • 25
  • 42
  • Totally. And you (Jonas) should use Assert.Equals : it calls the .Equals method if you pass an object to it (as opposed to Assert.AreSimilar) – Zonko Jan 31 '12 at 16:37
  • Documentation for the equality operator on strings says that it is implemented using the Equals function, so the results should be the same. http://msdn.microsoft.com/en-us/library/system.string.op_equality.aspx – David Merriman Jan 31 '12 at 16:41
  • This answered was more geared towards the reason his current unit test is failing. It provides a means to use his current test, compare two **Strings** the correct way, with the least amount of work. I agree that if **Assert.Equals()** is the way to compare two **String** objects then thats what he should use. I was going to verify how this method works, then I realized that, Redgates .NET Reflector was not installed on the machine I was looking at. – Security Hound Jan 31 '12 at 16:45
  • Assert.IsTrue(String.Compare("16 777 216", FormatDoubleWithThousandSeparator(16777216, 0)) == 0); Didn't work, it may be the case that there are a none printing character in the string. – Jonas Allansson Jan 31 '12 at 18:30
  • The spaces are different. "16 777 216"[6] -> 160 and FormatDoubleWithThousandSeparator(16777216, 0)[6] -> 32. The odd thing about this is that when I change the test from 16 777 216 to 1 000 the test passes. – Jonas Allansson Jan 31 '12 at 18:45