Skip to content

[API Proposal]: Span.StartsWith/EndsWith(T) #87689

Closed
@MihaZupan

Description

@MihaZupan

Background and motivation

string.StartsWith(char) and string.EndsWith(char) are useful shortcuts for this.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 on ReadOnlySpan<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

namespace 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 Designs

While most helpers on MemoryExtensions are available for both Span and ReadOnlySpan of any T, the vast majority of use for this one will likely end up being ReadOnlySpan<char>.

public static bool StartsWith(this System.ReadOnlySpan<char> span, char value);
public static bool EndsWith(this System.ReadOnlySpan<char> span, char value);

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.Memoryin-prThere is an active PR which will close this issue when it is merged

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions