-1

I have a method returning a List<GradingResult>:

   public class GradingResult
    {
        public float Grade { get; set; }
        public int Score { get; set; }
    }

That list has values from 6 to 1 in float format:

6, 5.9, 5.8, ... 1.2, 1.1,1

Now in my unit test I have a test GradingResult list with test data:

      new List<GradingResult> {

                 new GradingResult{ Score = 0,Grade = 6.0f},
                 new GradingResult{ Score = 1,Grade = 5.8f},
                 new GradingResult{ Score = 2,Grade = 5.7f},
                 new GradingResult{ Score = 3,Grade = 5.5f},
                 new GradingResult{ Score = 4,Grade = 5.4f},
                 new GradingResult{ Score = 5,Grade = 5.2f},
                 new GradingResult{ Score = 6,Grade = 5.1f},
                 new GradingResult{ Score = 7,Grade = 4.9f},
                 new GradingResult{ Score = 8,Grade = 4.7f},
                 new GradingResult{ Score = 9,Grade = 4.6f },
                 new GradingResult{ Score = 10, Grade = 4.4f },
                 new GradingResult{ Score = 11, Grade = 4.3f},
                 new GradingResult{ Score = 12, Grade = 4.1f},
                 new GradingResult{ Score = 13, Grade = 4.0f},
                 new GradingResult{ Score = 14, Grade = 3.8f},
                 new GradingResult{ Score = 15, Grade = 3.7f},
                 new GradingResult{ Score = 16, Grade = 3.5f},
                 new GradingResult{ Score = 17, Grade = 3.3f},
                 new GradingResult{ Score = 18, Grade = 3.2f},
                 new GradingResult{ Score = 19, Grade = 3.0f},
                 new GradingResult{ Score = 20, Grade = 2.9f},
                 new GradingResult{ Score = 21, Grade = 2.7f},
                 new GradingResult{ Score = 22, Grade = 2.6f},
                 new GradingResult{ Score = 23, Grade = 2.4f},
                 new GradingResult{ Score = 24, Grade = 2.2f},
                 new GradingResult{ Score = 25, Grade = 2.1f},
                 new GradingResult{ Score = 26, Grade = 1.9f},
                 new GradingResult{ Score = 27, Grade = 1.8f},
                 new GradingResult{ Score = 28, Grade = 1.6f},
                 new GradingResult{ Score = 29, Grade = 1.5f},
                 new GradingResult{ Score = 30, Grade = 1.3f},
                 new GradingResult{ Score = 31, Grade = 1.2f},
                 new GradingResult {Score = 32, Grade = 1.0f },
        }, "nextparameter"


            );

Now I compare the computed gradingResult with the test gradingResult via:

Assert.IsTrue(gradingResults.SequenceEqual(testGradingResults));

Test is not green, although the both result lists should be equal due to the definition here:

https://msdn.microsoft.com/en-us/library/bb348567(v=vs.100).aspx

My guess is that the whole grades like gradingResults 6,5,4,3,2,1 and the test gradingResults 6.0 , 5.0, 4.0, 3.0, 2.0, 1.0 are the cause of the failed test.

Can someone please shed some light on this situation please?

Why does the test fail? My sample is pretty similar to the Pets sample!

MethodMan
  • 18,625
  • 6
  • 34
  • 52
Elisabeth
  • 20,496
  • 52
  • 200
  • 321
  • 3
    Keep reading on that linked page. Don't stop after the first half. It specifically explains this exact problem. – Servy Jun 13 '16 at 21:25
  • Also, when you define "equality" for this type keep in mind that [floating point values that _look_ equal aren't always equal](http://stackoverflow.com/questions/17333) – D Stanley Jun 13 '16 at 21:44
  • Not only does it specifically explain the problem, as pointed out by Servy, it explains it *specifically for the Pets sample that you talk about in your question*... –  Jun 13 '16 at 21:58
  • I would recommend against using floats for quantities such as grades. A better choice would be either to use a normalized integer -- have grades like 600, 580, 120, etc, instead of 6.00, 5.80, 1.20 -- or use `decimal`. Remember `float` and `double` are for doing *physics* problems where small rounding issues do not matter. `decimal` is for doing problems where an exact representation of decimal quantities must be preserved. – Eric Lippert Jun 13 '16 at 22:31
  • @EricLippert A normalized integer? Why should I do 580 if 5.8 is correct? Then I would rather use Decimal. – Elisabeth Jun 14 '16 at 16:51
  • @Elisabeth: Because it is often *easier* and *safer* to do all arithmetic in integers, and then convert to a suitable display format at the last minute, than it is to attempt to do arithmetic in floating point formats. Many developers are unaware of how many theorems of regular arithmetic are not true of computer arithmetic. Computer arithmetic for example does not always obey the rule "things are always equal to themselves". It does not always obey the distributive property; a * (b + c) and a * b + a * c can have different values. By doing work in integers you minimize these problems. – Eric Lippert Jun 14 '16 at 17:46
  • @EricLippert Can we go on here? ;-) http://stackoverflow.com/questions/37820265/when-should-i-use-integer-for-arithmetic-operations-instead-of-float-double – Elisabeth Jun 14 '16 at 19:10

1 Answers1

1

You need to override the Equals and GetHashCode methods. Otherwise, it uses reference equality, and since the object in the lists are not the same instances, Equals returns false.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758