-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
[API Proposal]: Span.StartsWith/EndsWith(T) #87689
Comments
Tagging subscribers to this area: @dotnet/area-system-memory Issue DetailsBackground and motivation
The fact that Span is missing such a helper feels like an oversight on an otherwise helpful API surface of utility extensions and I often end up writing a helper class that polyfills these. A quick GH search shows ~10 other such places. It also means that some analyzers light up on I didn't find an existing issue for these so figured they're at least worth discussing. API Proposalnamespace System;
public static class MemoryExtensions
{
// Existing
public static bool StartsWith(this System.ReadOnlySpan<char> span, System.ReadOnlySpan<char> value, System.StringComparison comparisonType);
public static bool StartsWith<T>(this System.ReadOnlySpan<T> span, System.ReadOnlySpan<T> value) where T : System.IEquatable<T>?;
public static bool StartsWith<T>(this System.Span<T> span, System.ReadOnlySpan<T> value) where T : System.IEquatable<T>?;
// ... same pattern for EndsWith
// Proposed
public static bool StartsWith<T>(this System.ReadOnlySpan<T> span, T value) where T : System.IEquatable<T>?;
public static bool StartsWith<T>(this System.Span<T> span, T value) where T : System.IEquatable<T>?;
public static bool EndsWith<T>(this System.ReadOnlySpan<T> span, T value) where T : System.IEquatable<T>?;
public static bool EndsWith<T>(this System.Span<T> span, T value) where T : System.IEquatable<T>?;
} API Usage-static bool IsNameHidden(ReadOnlySpan<char> fileName) => fileName.Length > 0 && fileName[0] == '.';
+static bool IsNameHidden(ReadOnlySpan<char> fileName) => fileName.StartsWith('.'); Alternative DesignsWhile most helpers on public static bool StartsWith(this System.ReadOnlySpan<char> span, char value);
public static bool EndsWith(this System.ReadOnlySpan<char> span, char value); RisksNo response
|
Likely these don't exist because you can do: // For non-reference types
MemoryExtensions.StartsWith(somespan, stackalloc[] {somevalue}); |
@MihaZupan should we also consider |
Do you mean something like a static bool StartsWithAny<T>(ReadOnlySpan<T> span, SearchValues<T> values) =>
span.Length > 0 && values.Contains(span[0]); Things like Something like a Or did I misunderstand your question? |
Yup, no that was my question indeed — I can see how it might probably be niche, plus the fact you can just roll your own version still leveraging Thanks! |
any chance of this getting into v9? |
Wondering if it could make more sense to just add |
@dotnet/area-system-memory should this one be marked as ready for review? |
We do provide similar overloads on string and it is quite convenient overall, so I'd lean towards marking this We could make some overloads CC. @stephentoub, @GrabYourPitchforks for additional input. |
Seems fine. Assuming the first-class span support lands, we wouldn't need the Span-based overloads, just the ReadOnlySpan-based overloads.
I'm not following. All of the proposed overloads just take a |
Right, sorry, that's more what I meant. Was mostly just thinking now that we have Having an explicit overload that just takes 1 value and does the least amount of checks/overhead is still goodness I think, though. |
Agreed. This seems like the most common use case. |
Looks good as proposed. There was a question of whether we're missing something by not having namespace System;
public static partial class MemoryExtensions
{
public static bool StartsWith<T>(this System.ReadOnlySpan<T> span, T value) where T : System.IEquatable<T>?;
public static bool StartsWith<T>(this System.Span<T> span, T value) where T : System.IEquatable<T>?;
public static bool EndsWith<T>(this System.ReadOnlySpan<T> span, T value) where T : System.IEquatable<T>?;
public static bool EndsWith<T>(this System.Span<T> span, T value) where T : System.IEquatable<T>?;
} |
Do we need the |
We shouldn't need them, the first-class spans proposal is specifically targeted at scenarios like this. /cc @jjonescz. |
Background and motivation
string.StartsWith(char)
andstring.EndsWith(char)
are useful shortcuts forthis.Length > 0 && this[0] == 'a'
.They also sometimes save you from having to declare temporary locals
SomeCall().StartsWith('a')
.For strings, they are also more efficient now but that's not the main motivation and likely wouldn't apply to Span extensions.
The fact that Span is missing such a helper feels like an oversight on an otherwise helpful API surface of utility extensions and I often end up writing a helper class that polyfills these. A quick GH search shows ~10 other such places.
It also means that some analyzers light up on
string
, but not onReadOnlySpan<char>
, e.g. the recently added CA1858 - "Use StartsWith instead of IndexOf".I didn't find an existing issue for these so figured they're at least worth discussing.
At least unlike most? other extensions (e.g.
IndexOf
,StartsWith(ReadOnlySpan, ReadOnlySpan)
...), these methods are trivial to polyfill without losing out on potential perf.Edit: more discussion around these APIs also at #85374
API Proposal
API Usage
Alternative Designs
While most helpers on
MemoryExtensions
are available for bothSpan
andReadOnlySpan
of anyT
, the vast majority of use for this one will likely end up beingReadOnlySpan<char>
.Risks
No response
The text was updated successfully, but these errors were encountered: