{"record":{"id":"022e55644d5798f0","repo":"TheAlgorithms/C-Sharp","slug":"comparison-method-violates-its-general-contract","errorCode":null,"errorMessage":"Comparison method violates its general contract!","messagePattern":"Comparison method violates its general contract!","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Algorithms/Sorters/Comparison/TimSorter.cs","lineNumber":211,"sourceCode":"        return true;\n    }\n\n    /// <summary>\n    /// Moves over the last parts of the chunks.\n    /// </summary>\n    /// <param name=\"left\">TimChunk of the left hand side.</param>\n    /// <param name=\"right\">TimChunk of the right hand side.</param>\n    /// <param name=\"dest\">The current target point for the remaining values.</param>\n    private static void FinalizeMerge(TimChunk<T> left, TimChunk<T> right, int dest)\n    {\n        if (left.Remaining == 1)\n        {\n            Array.Copy(right.Array, right.Index, right.Array, dest, right.Remaining);\n            right.Array[dest + right.Remaining] = left.Array[left.Index];\n        }\n        else if (left.Remaining == 0)\n        {\n            throw new ArgumentException(\"Comparison method violates its general contract!\");\n        }\n        else\n        {\n            Array.Copy(left.Array, left.Index, right.Array, dest, left.Remaining);\n        }\n    }\n\n    /// <summary>\n    /// Returns the length of the run beginning at the specified position in\n    /// the specified array and reverses the run if it is descending (ensuring\n    /// that the run will always be ascending when the method returns).\n    ///\n    /// A run is the longest ascending sequence with:\n    ///\n    ///    <![CDATA[a[lo] <= a[lo + 1] <= a[lo + 2] <= ...]]>\n    ///\n    /// or the longest descending sequence with:\n    ///","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/TheAlgorithms/C-Sharp/blob/96e2905cab7bc6b33ac0a34ee5bb82ddccbcbb6c/Algorithms/Sorters/Comparison/TimSorter.cs#L193-L229","documentation":"TimSorter's FinalizeMerge throws ArgumentException(\"Comparison method violates its general contract!\") when a merge finishes with left.Remaining == 0, meaning the comparator produced an inconsistent ordering — elements were neither strictly ordered nor correctly interleaved. This is the classic TimSort invariant break caused by a comparator that violates transitivity/antisymmetry (e.g. returning 0 for non-equal items or inconsistent results across calls).","triggerScenarios":"Sorting with a comparison delegate that is not a valid total order: Compare(a,b) inconsistent with Compare(b,a), non-transitive results, comparator returning inconsistent values for the same pair across calls (mutable keys), or subtracting ints and overflowing instead of returning -1/0/1.","commonSituations":"Comparators written as (a,b) => a.Value - b.Value that overflow; sorting objects whose key changes during the sort (multi-threaded mutation); comparators using floating-point or null handling inconsistently; code updated to a new TimSort-style sort after working with an older, less strict sort algorithm.","solutions":["Fix the comparator to be a consistent total order: return -1/0/1 explicitly, never rely on integer subtraction that can overflow.","Make comparator results stable: do not sort objects whose comparison key mutates mid-sort.","Ensure Compare(a,b) == -Compare(b,a) and transitivity holds; add a unit test that checks these properties on representative data.","If a subset triggers it, isolate the data and log the offending pairs to find the inconsistent comparison."],"exampleFix":"// before\nlist.Sort((a, b) => a.Score - b.Score);\n// after\nlist.Sort((a, b) => a.Score.CompareTo(b.Score));","handlingStrategy":"validation","validationCode":"// Verify comparator consistency before sorting:\nstatic bool IsConsistent<T>(Comparison<T> cmp, IEnumerable<T> sample) =>\n    sample.All(a => sample.All(b =>\n        Math.Sign(cmp(a, b)) == -Math.Sign(cmp(b, a))));","typeGuard":null,"tryCatchPattern":"try { sorter.Sort(data); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"general contract\")) { /* fall back to a safe comparator, e.g. Comparer<T>.Default */ }","preventionTips":["Use CompareTo instead of subtraction in comparators to avoid overflow.","Never mutate sort keys while a sort is in progress.","Property-test comparators for transitivity and antisymmetry.","Return only -1/0/1 (via Math.Sign) from custom comparisons."],"tags":["sorting","comparator","timsort","contract-violation"],"backgroundTag":"invalid-argument-value","analyzedSha":"96e2905cab7bc6b33ac0a34ee5bb82ddccbcbb6c","analyzedAt":"2026-09-13T17:04:01.438Z","contentChangedAt":"2026-09-13T17:04:01.438Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}