-
-
Notifications
You must be signed in to change notification settings - Fork 182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Regression] Exception when using .Sort with comparerChanged overload and AddRange #473
Comments
I was not aware that anything has changed with sort for quite some time. I'll take a look at the source code history. Also it has always been by design to not tick until a comparer is specified. The easy solution is to use BehaviorSubject. |
Maybe that's because we are really slow at updating dependencies :-D The package is available since November 2020...
That's how it was in 6.17.14, but in 7.1.1 it throws an Exception and there are no items ticked, even after the comparer is specified. When you run the sample, there are no items written to the console at the end. For this sample, when using a var sorter = new BehaviorSubject<IComparer<ListItem>>(new NullComparer());
//...
internal class NullComparer : IComparer<ListItem>
{
public int Compare(ListItem x, ListItem y)
{
return 0;
}
} Output
|
I tried to fix this with a BehaviorSubject in our production app, but it still failed. I updated the repro slightly to highlight the issue.: When adding the items before connecting, even the BehaviorSubject is "too late" to tick the comparer and the Exception is thrown again. We create dynamic groups (based on the XamarinFormsGrouping Snippet) and pass the comparer inside to also sort the items inside the group. The list is always filled before the group is created, so I don't think we can do much else on this front. I also tried implementing my own .Sort operator with a |
Thanks for the reproduction. The reason as you suggest for the error is timing. Within the sort code, the changes are subscribed to before the comparer changed stream, which means that the code tries to sort using the default object comparer which expects the object to implement IComparable. A simple solution around this would be to implement internal class ListItem: IComparable<ListItem>
{
public static readonly IComparer<ListItem> DefaultComparer = SortExpressionComparer<ListItem>.Ascending(x => x.Number);
public int Number { get; }
public ListItem(int number)
{
Number = number;
}
public int CompareTo(ListItem other) => DefaultComparer.Compare(this, other);
} The fix within Dynamic Data will be to subscribe to the comparer changes before subscribing to item changes. I'll try this out and if it works will merge it. |
Doh, I did the investigation after reading the first comment. Now I have scrolled down and seen that you had worked out the same. In case you did not know the "pseduo-comparer" method is exactly what all primitives implement. That's why for the error would not occur if you are sorting built in structures. What I am still unsure of is why the error only occurs for you after an upgrade, |
Interesting, I didn't know that! I'll try implementing It looks like this line is the culprit: src/DynamicData/List/Internal/Sort.cs#L34 Also, this seems to be only regarding List, not Cache: src/DynamicData/Cache/Internal/Sort.cs |
Allow empty notifications for cache + Ensure comparer changed is subscribed to before data changed for list. Fixes #473
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
After upgrading from DynamicData 6.x to 7.x, my ListViews (Xamarin.Forms) were suddenly empty. Fortunately there was an Exception thrown and with that information I could narrow the problem down to the following:
When using
.Sort(IObservable<IComparer<T>> comparerChanged)
, then an initial.AddRange
will basically be ignored, unlessobserverChanged
ticked at least one value orT
implementsIComparable
.You can repro this with the following small example:
ReproDynamicDataSort.zip
The sample is really simple, it creates a
SourceList
, passes the sorter and then adds 10 items. The key part is that the sorter does not tick before the items are added, e.g. switching the last 2 lines will make the code work. Unfortunately, I have cases where I do not know the order beforehand, so I cannot do something like this in my production code.It seems that since DynamicData 7.x, the internal comparer is initialized with
Comparer<T>.Default
, which needs the items to implementIComparable
. Whereas in DynamicData 6.x, there was a fallback for when there is no comparer available. From my point of view, it should be sufficient to implement that fallback again.The text was updated successfully, but these errors were encountered: