Fix selection being dropped when changing carousel sort mode from difficulty sort #29786
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Closes #29738.
This "regressed" in #29639, but if I didn't know better, I'd go as far as saying that this looks like a .NET bug, because the fact that PR broke it looks not sane.
The TL;DR on this is that before the pull in question, the offending
.Contains()
check that this commit modifies was called on aList<BeatmapSetInfo>
. The pull changed the collection type toBeatmapSetInfo[]
. That said, the call is a LINQ call, so all good, right?Not really. First off, the default overload resolution order means that the previous code would call
List<T>.Contains()
, and notEnumerable.Contains<T>()
. Then again, why would that matter? In both casesT
is stillBeatmapSetInfo
, right? Well... about that...It is difficult to tell for sure what precisely is happening here, because of what looks like runtime magic. The end symptom is that the old code ended up calling
Array<BeatmapSetInfo>.IndexOf()
, and the new code ends up calling...Array<object>.IndexOf()
.So while yes,
BeatmapSetInfo
implementsIEquatable
and the expectation would be thatEquals<BeatmapSetInfo>()
should be getting called, the type elision toobject
means that we're back to reference equality semantics, because that's whatEqualityComparer.Default<object>
is.A five-minute github search across dotnet/runtime yields this. Now again, if I didn't know better, I'd see that "OPTIMIZATION:" comment, see what transpired in this scenario, and call that optimisation invalid, because it changes semantics. But I probably know that the dotnet team knows better and am probably just going to take it for what it is, because blame on that code looks to be years old and it's probably not a new behaviour. (I haven't tested empirically if it is.)
Instead the fix is just to tell the
.Contains()
method to use the correct comparer.