[API Proposal]: Add SearchValues.CreateRange
- 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
Assessment
This issue has not been assessed yet.