{"record":{"id":"13be450e93ce85ad","repo":"stride3d/stride","slug":"no-comparison-available-or-provided-for-items-of-this","errorCode":null,"errorMessage":"No comparison available or provided for items of this collection.","messagePattern":"No comparison available or provided for items of this collection\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation/Collections/SortedObservableCollection.cs","lineNumber":126,"sourceCode":"        {\n            if (typeof(T).GetInterfaces().Contains(typeof(IComparable<TSearch>)))\n                compareFunc = (item1, item2) => ((IComparable<TSearch>)item1!).CompareTo(item2);\n            else\n                throw new ArgumentNullException(nameof(compareFunc));\n        }\n\n        return GetIndex(key, false, compareFunc);\n    }\n\n    /// <inheritdoc/>\n    public override string ToString()\n    {\n        return $\"{{SortedObservableCollection}} Count = {Count}\";\n    }\n\n    protected int GetIndex(T item, bool returnInsertIndex)\n    {\n        if (DefaultCompareFunc is null) throw new InvalidOperationException(\"No comparison available or provided for items of this collection.\");\n        return GetIndex(item, returnInsertIndex, DefaultCompareFunc.Invoke);\n    }\n\n    protected int GetIndex<TSearch>(TSearch key, bool returnInsertIndex, Func<T, TSearch, int> compareFunc)\n    {\n        int imin = 0;\n        int imax = Count - 1;\n        while (imax >= imin)\n        {\n            int imid = (imin + imax) / 2;\n\n            int comp = compareFunc(this[imid], key);\n            if (comp < 0)\n                imin = imid + 1;\n            else if (comp > 0)\n                imax = imid - 1;\n            else\n                return imid;","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation/Collections/SortedObservableCollection.cs#L108-L144","documentation":"GetIndex locates (or computes the insert index for) an item via DefaultCompareFunc. If no comparison function is available (null) when GetIndex is invoked — e.g. the collection was created through a path that skipped comparer resolution — it throws InvalidOperationException instead of silently mis-ordering.","triggerScenarios":"Calling methods that rely on GetIndex (insert, binary search, index lookup) on a SortedObservableCollection whose DefaultCompareFunc is null — typically via a constructor path that did not resolve a comparer, or after the comparer was cleared.","commonSituations":"Subclasses that bypass the validating constructor; deserialization rebuilding the collection without a comparer; calling protected sorting helpers on a badly initialized instance.","solutions":["Recreate the collection with a valid comparer or ensure T implements IComparable","Pass a comparison function through the constructor overload used by your subclass","Check the initialization path (e.g. deserialization) that produced a comparer-less collection","Call the GetIndex overload that takes an explicit compareFunc when no default is available"],"exampleFix":"// before\nvar idx = col.GetIndex(item, false); // DefaultCompareFunc null\n// after\nvar col = new SortedObservableCollection<MyVm>(Comparer<MyVm>.Create((a, b) => a.Name.CompareTo(b.Name)));\nvar idx = col.GetIndex(item, false);","handlingStrategy":"validation","validationCode":"var safeCol = col.DefaultCompareFunc != null ? col : new SortedObservableCollection<T>(Comparer<T>.Create(cmp));","typeGuard":null,"tryCatchPattern":"try { var idx = col.GetIndex(item, false); } catch (InvalidOperationException) { /* comparer missing; rebuild collection with comparer */ }","preventionTips":["Construct SortedObservableCollection only through constructors that resolve a comparer","Rebuild with a comparer after deserialization","Pass an explicit compareFunc when invoking index-search helpers on subclasses"],"tags":["collections","sorting","comparer"],"backgroundTag":"missing-required-argument","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}