0

I have the following code, which produces different outputs depending on the project I run it from. All project properties look the same and it's both using the same lib.

List<(string, int)> numbers = new List<(string, int)>() { ("ID", 0), ("AL", 0), ("D2", 50), ("D3", 50), ("D4", 50) };

        int counter = 0;

        numbers.Sort(delegate ((string, int) item1, (string, int) item2)
        {
            int change = item1.Item2.CompareTo(item2.Item2);

            counter++;

            return change;
        });

        string ans2 = String.Join(" ", numbers.Select(item => item));

The sort method is from System.Collections.Generic. #region Assembly mscorlib, Version=4.0.0.0, Culture=neutral

.Net Framework 4.7.2 Project1:

The final result is "(AL, 0) (ID, 0) (D4, 50) (D3, 50) (D2, 50)" The counter is 20.

.Net Framework 4.7.2 Project2:

The counter is 4.

The final result is "(ID, 0) (AL, 0) (D2, 50) (D3, 50) (D4, 50)"

Can anyone help me understand why the different iteration counts and outputs are different?

I understand the List.Sort() performs an unstable sort, which means that if two elements are equal their order might not be preserved. But it still does not explain the iteration difference.

Bijaya Rai
  • 43
  • 8
  • 1
    Maybe because your `CompareTo` only compares the integer value and nothing else, therefore the order of elements with same integer value is undetermined. Do you always get the same results for a given project? – Rafalon Jan 28 '21 at 15:34
  • Does it depend on the project or the machine it runs on? Perhaps check with a [debugger](https://stackoverflow.com/questions/54774515/how-to-debug-into-net-framework-source-code) what code actually runs the sorting in each case? In any case, you should not depend on the exact ordering since it is not stable. The list is correctly sorted in both cases, and the exact implementation can, and has, changed. – JonasH Jan 28 '21 at 15:37
  • 1
    As the documentation of `List.Sort()` states it performs an unstable sort: the way it internally works isn't your business. It looks like between project 1 and project 2 the sort method iterates the array from top or botton. This can't be predictable. You could even experience different behaviour when running the same project several times in differents conditions. You may fix your compared to compare the number and then then the string if `int.CompareTo()` return 0. – StringBuilder Jan 28 '21 at 15:47
  • A better question would be why you care -- if you need a stable sort, why not just use one? (`Enumerable.OrderBy` is such a sort, or you could of course make the keys unique somehow.) An unstable sort is explicitly permitted to not only give different results between projects, but between runs of the exact same code; while it may be an interesting exercise to see where the difference is coming from in this particular case, finding out will likely not lead to any kind of solution. – Jeroen Mostert Jan 28 '21 at 15:47
  • @JeroenMostert Is it possible to perform an orderBy on a class that implemtens a list. E.g. class Foos: List{} – Bijaya Rai Jan 29 '21 at 10:05
  • @JonasH It looks like project2 uses IntroSort(..) from arraysorthelper.cs where as project1 uses DepthLimitedQuickSort(..) method to sot the items. Just out of curiosity, is there a way to pick a specific sorting method? – Bijaya Rai Jan 29 '21 at 10:10
  • @Bijaya Rai Yes, you can write your own sort method. That way you are guaranteed consistent behavior. If you use framework methods you can only guarantee that they fulfills the contract they provide. If I decompile my version it runs introspective sort if `BinaryCompatibility.TargetsAtLeast_Desktop_V4_5`, so either that is false for one project, or your framework version has another check. – JonasH Jan 29 '21 at 10:24
  • `Enumerable.OrderBy` will work on anything that implements `IEnumerable`, which includes `List`. You cannot override the `Sort` method because it's not marked `virtual`, so if clients call on `List.Sort` exclusively to get the job done you're stuck. (You could hide the old method and declare another with `new`, but this only works if clients use your class explicitly, not if they call through `List`.) – Jeroen Mostert Jan 29 '21 at 11:14

0 Answers0