You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature]: Keep dedicated .Sort(), instead of deprecating聽#963
With the .Sort() method being depreciated there are a couple of rare cases where applying a sort immediately is desired because the properties used in the comparison do not exist downstream.
example:
changeSet
.Sort(complexSortComparer) //Sorts on input data type
.DistinctValues(x => x.Name) //DistinctValues is transforming to Name data type
.Bind(out names); //List of names is sorted
Changing the call chain to use SortAndBind() is not possible in this scenario.
The second scenario is pretty compelling to me, as a potential performance improvement for not duplicating sort work. However, I also proposed in the thread that the performance of .Sort() is so poor that one instance of .Sort() might actually NOT be more efficient thant two instances of .SortAndBind(). Now, I'm curious to benchmark it.
I think I came across another scenario where there's a use case for sorting before binding. If the output collection is a base type, but the observable stream coming in is a derived type.
If there's an elegant work around I'm not seeing, please let me know :)
I am a bit late to this show. I meant to respond and promptly forgot.
There is a potentially a solution, and that is to take advantage of the list operators which respect sorted data sets (mostly). Try changing the cache to a list by removing the keys before Sort like this:
changeSet.RemoveKey()// This converts the operator into a list operator which is index based..Sort(complexSortComparer)//Sorts on input data type.DistinctValues(x =>x.Name)//DistinctValues is transforming to Name data type .Bind(outnames);//List of names is sorted
I will switch our organization's apps to Roland's suggestion over time. I tested with one project and it seems to work just fine.
I had thought there were some issues with SourceList that didn't occur when using a SourceCache, but maybe those problems were fixed in PR #1009. My requirements for .Sort() before .Bind() are so simple I think it doesn't matter and this will work.
@RolandPheasant the second scenario I posted where the cache is a derived type but the output collection is a base type, is there a work around for that? Or is there a covariance issue with the Bind() or SortAndBind() methods? (See my comment on Feb 3)
there were some issues with SourceList that didn't occur when using a SourceCache
SourceList is fine, it's just limited by a difficulty to ensure good performance. The existing operators are sound and should work well. The only "issue" is that I drew a line in the sand and limited source list to certain operators only. In practise however, I have only ever had a few scenarios where I could not use a cache key or manufacture a quasi one - hence the limited scope.
The advantage however with using the list is that it is naturally suited to binding as a bound list is indexed based and for the most part respected the order.
Of the basic list operators, it is only Filter() which does not preserve the order. It's probably possible to fix this, but would require a fair bit of effort.
Of the basic list operators, it is only Filter() which does not preserve the order. It's probably possible to fix this, but would require a fair bit of effort.
It's worth noting that this is now a proven concept. #1063 hasn't been merged yet, but it accomplishes preservation of order, through a .Filter() without significant loss of performance. We actually GAIN performance overall, due to just general optimizations that come with re-writing an operator from scratch. Currently, it's only the "static" variation of .Filter() that's been updated (I.E. the one where filtering criteria can't change over time), but we should be able to extend this proof of concept to all .Filter() variations.
Activity
JakenVeina commentedon Dec 7, 2024
Additional scenarios we discussed...
The second scenario is pretty compelling to me, as a potential performance improvement for not duplicating sort work. However, I also proposed in the thread that the performance of
.Sort()is so poor that one instance of.Sort()might actually NOT be more efficient thant two instances of.SortAndBind(). Now, I'm curious to benchmark it.jbooth88 commentedon Feb 3, 2025
I think I came across another scenario where there's a use case for sorting before binding. If the output collection is a base type, but the observable stream coming in is a derived type.
If there's an elegant work around I'm not seeing, please let me know :)
[-][Feature]: [/-][+][Feature]: Keep dedicated .Sort(), instead of deprecating[/+]RolandPheasant commentedon Jun 4, 2025
I am a bit late to this show. I meant to respond and promptly forgot.
There is a potentially a solution, and that is to take advantage of the list operators which respect sorted data sets (mostly). Try changing the cache to a list by removing the keys before
Sortlike this:giard-alexandre commentedon Jun 4, 2025
@RolandPheasant how performant is that solution? Seems to me like this SHOULD be decent as long as a user is smart about what comes AFTER the sort?
RolandPheasant commentedon Jun 5, 2025
The performance should be similar to the original cache sort.
jbooth88 commentedon Jun 5, 2025
I will switch our organization's apps to Roland's suggestion over time. I tested with one project and it seems to work just fine.
I had thought there were some issues with SourceList that didn't occur when using a SourceCache, but maybe those problems were fixed in PR #1009. My requirements for .Sort() before .Bind() are so simple I think it doesn't matter and this will work.
@RolandPheasant the second scenario I posted where the cache is a derived type but the output collection is a base type, is there a work around for that? Or is there a covariance issue with the Bind() or SortAndBind() methods? (See my comment on Feb 3)
RolandPheasant commentedon Jun 7, 2025
SourceList is fine, it's just limited by a difficulty to ensure good performance. The existing operators are sound and should work well. The only "issue" is that I drew a line in the sand and limited source list to certain operators only. In practise however, I have only ever had a few scenarios where I could not use a cache key or manufacture a quasi one - hence the limited scope.
The advantage however with using the list is that it is naturally suited to binding as a bound list is indexed based and for the most part respected the order.
@jbooth88
Should working fine. Try it out an let me know.
Of the basic list operators, it is only
Filter()which does not preserve the order. It's probably possible to fix this, but would require a fair bit of effort.JakenVeina commentedon Feb 27, 2026
It's worth noting that this is now a proven concept. #1063 hasn't been merged yet, but it accomplishes preservation of order, through a
.Filter()without significant loss of performance. We actually GAIN performance overall, due to just general optimizations that come with re-writing an operator from scratch. Currently, it's only the "static" variation of.Filter()that's been updated (I.E. the one where filtering criteria can't change over time), but we should be able to extend this proof of concept to all.Filter()variations.