-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Background and motivation
We recently added:
public static void Replace<T>(this Span<T> span, T oldValue, T newValue) where T : IEquatable<T>?and we've been able to use it ourselves in several places, e.g. in StringBuilder.Replace. However, there are several places that actually want to be able to perform a copy/replace operation together, and doing so as a copy followed by a replace can be significantly slower (upwards of 2x) than a combined operation. For example, string.Replace needs to copy into a separate buffer and perform the replace in that buffer, and https://github.com/dotnet/aspnetcore/blob/287d7eab1c644bce2d4c96751bc3d323362b1bb7/src/Shared/QueryStringEnumerable.cs#L166-L229 similarly copies from a ReadOnlySpan<char> to a Span<char> doing a replace in the process.
We already have the implementation for this as part of string.Replace, so this is effectively just exposing that through an additional Replace overload, which can then be used in other places, like in ASP.NET.
API Proposal
namespace System
public static class MemoryExtensions
{
public static void Replace<T>(this Span<T> span, T oldValue, T newValue) where T : IEquatable<T>?
+ public static void Replace<T>(this ReadOnlySpan<T> source, Span<T> destination, T oldValue, T newValue) where T : IEquatable<T>?
}API Usage
// Create a string from the ReadOnlySpan<char>, replacing all pluses with spaces.
return string.Create(source.Length, (IntPtr)(&source), (dest, rosPtr) =>
{
ReadOnlySpan<char> source = *(ReadOnlySpan<char>*)rosPtr;
source.Replace(dest, '+', ' ');
});Alternative Designs
No response
Risks
No response