Repository navigation
Fixed bogus lookup logic within list-land .TransformAsync(),… - #1171
JakenVeina wants to merge 11 commits into
Conversation
…ocessing changes with unspecified indexes, which resulted in `Remove` and `RemoveRange` changes with unspecified indexes to be ignored completely.
ed51f2a to
18b0f53
Compare
RemoveWithoutIndex and RemoveRangeWithoutIndex were added by #1171 and dropped while rebasing the global usings onto it.
dwcullop
left a comment
There was a problem hiding this comment.
Fix looks right to me. Matching on EqualityComparer<TSource>.Default lines up with how TransformedItemContainer already defines equality.
The synchronous Transform has the same bug, though, so it'd be good to fix both here:
List/Internal/Transformer.cs:146and:165match indexless removes withReferenceEquals(t.Source, change.Current). For value types that's always false because both sides get boxed, so an indexlessRemove/RemoveRangeofints is silently dropped, which is exactly #1169.- The
RemoveRangebranch there (Where(t => item.Range.Any(...))intoRemoveMany) also removes every duplicate of an item, not one per entry in the range. TransformFixture.RemoveWithoutIndexonly usesPerson, so nothing catches it. Mirroring your two newinttests againstTransformwould.
As it stands sync and async also disagree on what "the same item" means (reference identity vs Equals), which seems worth closing while we're here.
Small nit on the lookup itself: the Select((pair, index) => (sourceItem, (int?)index)).FirstOrDefault(...).index trick takes a second read, allocates per remove, and is duplicated. A plain index loop in one helper that both Transformer and TransformAsync call would be simpler and keeps the two operators from drifting again.
79fb9b0 to
43f46bc
Compare
|
Fair point about putting equivalent fixes on I'm not too fussed about the optimalness of the index lookup, when that's SUCH a "this really shouldn't be a thing" scenario, but looking at it, I realized there were actually several OTHER inconsistencies (for other change types) in how index lookups are being done, across both operators. So yeah, I just added a helper method and refactored it into both operators, everywhere an index lookup is needed. There's still inconsistencies in how the operators handle an index lookup that FAILS (some change types will throw, some will just silently ignore the change) but I opted to just preserve the existing logic, rather than expand scope any further. A failed index lookup really is just an extension of changeset corruption, which is not really this PR's problem to deal with. |
…d logic for handling index lookup, when indexes are missing from changesets, into a shared allocation-free helper method.
43f46bc to
4d81cb1
Compare
… for processing changes with unspecified indexes, which resulted in
RemoveandRemoveRangechanges with unspecified indexes to be ignored completely.