dotnet / dotnet/runtime

[API Proposal]: Add SearchValues.CreateRange

Open
#129,283 15 comments 0 reactions 0 assignees View on GitHub
api-suggestion area-System.Memory
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Background and motivation

I'm proposing a new way of creating `SearchValues` - instead of some values, it would represent a range of values. I know I can achieve this via `IndexOfAnyInRange`, but encapsulating the search inside `SearchValues` seems like a much better design to me than method explosions like this, and the methods I mentioned would be now unnecessary and effectively obsolete. It would be convenient to be able to always store `SearchValues`, even in case of ranges, and then use the one method that uses it.

### API Proposal

```c#
namespace System.Buffers;

public static partial class SearchValues
{
public static SearchValues Create(scoped ReadOnlySpan values)
where T : IBinaryInteger;

public static SearchValues CreateRange(T lowInclusive, T highInclusive)
where T : IBinaryInteger;

public static SearchValues CreateRanges(params scoped ReadOnlySpan> ranges)
where T : IBinaryInteger;

public readonly struct Range : IEquatable>
where T : IBinaryInteger
{
public Range(T value);
public Range(T lowInclusive, T highInclusive);

public T LowInclusive { get; }
public T HighInclusive { get; }

public void Deconstruct(out T lowInclusive, out T highInclusive);

public static implicit operator Range(T value);
public static implicit operator Range((T lowInclusive, T highInclusive) range);
}
}
```

Note: The T might have to be expanded to a list of overloads for concrete types instead of being generic.

Also, if I'm unsure whether to use CreateRange with 2 or 3 sequential elements or Create with those elements, no matter what I pick, it would be nice if the implementation chose the right and fastest form of searching for such a set no matter which method I choose, so I don't have to worry about it. Tbat's the benefit of using SearchValues, even for ranges.

### API Usage

```c#
var searchValues = SearchValues.CreateExceptRange('a', 'z');
var index = span.IndexOfAny(searchValues);

var invalidChars = SearchValues.CreateRanges(((char)0, (char)31), '@', '#', '|');
var index2 = span.IndexOfAny(invalidChars);

// or, get all control characters except for newline
var invalidChars2 = SearchValues.CreateRanges(((char)0, (char)9), ((char)11, (char)31));
```

### Alternative Designs
As an alternative, only the `CreateRange` and `CreateRanges` APIs could be added - those are the ones I'd like to use.

### Risks

Idk. cc @stephentoub

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.