Open YohDeadfall opened 1 year ago
Tagging subscribers to this area: @dotnet/area-system-memory See info in area-owners.md if you want to be subscribed.
Author: | YohDeadfall |
---|---|
Assignees: | - |
Labels: | `api-suggestion`, `area-System.Memory` |
Milestone: | - |
I don't think it's possible to add IComparer<T>
overload to existing API without losing performance. Right now it uses Avx2 and per-byte comparison for values. Using any comparer, even default, will make it much slower.
Right now it uses Avx2 and per-byte comparison for values. Using any comparer, even default, will make it much slower.
Don't see it:
If there's no comparer or it is a default one, then fallback to an overload without a comparer as it happens for equality.
Is there anything preventing this from being ready to review?
This is the proposal next to the existing methods, for reference:
namespace System;
public static partial class MemoryExtensions
{
public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other) where T : IEquatable<T>?;
public static bool SequenceEqual<T>(this Span<T> span, ReadOnlySpan<T> other) where T : IEquatable<T>?;
public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other, IEqualityComparer<T>? comparer = null);
public static bool SequenceEqual<T>(this Span<T> span, ReadOnlySpan<T> other, IEqualityComparer<T>? comparer = null);
public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other) where T : IComparable<T>?;
public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other) where T : IComparable<T>?;
+ public static int SequenceCompareTo(this ReadOnlySpan<T> span, ReadOnlySpan<T> other, IComparer<T>? comparer = null);
+ public static int SequenceCompareTo(this Span<T> span, ReadOnlySpan<T> other, IComparer<T>? comparer = null);
}
@YohDeadfall You should change the Span<T>
overload to take ReadOnlySpan<T>
as the second argument, not Span<T>
, just like the existing overload always take a ReadOnlySpan<T>
as the second argument (and like I showed in the comment above). There's no need to require it to be mutable. The only reason there are overloads for the first argument being both readonly and non-readonly is that when it only takes ReadOnlySpan<T>
, the extension method wouldn't show up on Span<T>
. But this is not a problem for the other arguments.
Also, MemoryExtensions
is in System
, not System.Collections.Generic
.
@Neme12, thank you! Fixed the proposal.
Background and motivation
The
MemoryExtensions
type providesSequenceCompareTo
methods which has just two overloads, but none of them is accepting a custom element comparer making it impossible to compare two sequences without allocating new buffers or without implementing the required overload outside of the standard library.At the same time the type has overloads accepting a custom equality comparer for equality comparison.
If it's approved, I would like to provide an implementation for it.
API Proposal
API Usage
Alternative Designs
When two input sequences are arrays, then one of them can be casted to
IStructuralComparable
and do comparison, but that solution isn't obvious because the interface is implemented explicitly. In addition to thatCompareTo
of the interface accepts a non-genericIComparer
which looses type safety and potentially hurts performance (if there's no under the hood cast of the passed comparer toIComparer<T>
to be used then).If both sequences were received as spans, then to use the mentioned alternative solution
ToArray
must be called on the spans which leads to unwanted memory allocations.Risks
No response