.agents/skills/performance-fixer/references/bcl-patterns/strings-and-spans.md
General .NET fast-string techniques, applied to SkiaSharp's managed layer. Prefer the BCL here;
use a shared helper only for the specific benefit it documents (../repo-helpers.md).
Mind all TFMs — SkiaSharp targets net462/netstandard2.0 → net10; guard newer APIs with #if and
provide a correct fallback. See ../decision-framework.md for the
complexity rubric and ../measuring.md to verify.
ReadOnlySpan<char>/Span<T> overload so callers parse/convert out of a larger
buffer without allocating a substring; the string overload delegates via .AsSpan().Substring/new string at every call site.System.Memory) · ABI: additive overload — never replace
the T[]/string one.SKColor.Parse, SKFourByteTag.Parse, HarfBuzzSharp.Tag/Feature/Script (see
../hot-paths/color.md).[MethodImpl(AggressiveInlining)] nibble
helper straight into the target uint/int.byte.TryParse/uint.TryParse with NumberStyles.HexNumber + CultureInfo, or
new string(char, n) per channel.#if TFM
splits into one path. #4345: zero-alloc, 1.4–2.3×.null/empty/#/named-color rejection.destination.TryWrite($"{a}:{b}", out var n) or value.TryFormat(dst, out n) to write
directly into a Span<char>.string.Format/ToString into a temporary then copying.object[], and the intermediate string.TryWrite net6+ (fall back to TryFormat/manual) · ABI: internal.string.Create(len, state, static (span, s) => { ... }) to build the final string in one
allocation.StringBuilder + ToString, or concatenation, when the length is known.static lambda avoids a closure capture.net462/
netstandard2.0; guard #if with a StringBuilder/char[] fallback there · ABI: internal.u8) for constant byte prefixes"\r\n--"u8 for constant ASCII/UTF-8 data copied into a native buffer.Encoding.UTF8.GetBytes("...") of a constant at runtime.For repeated char/byte-set scanning (IndexOfAny over a literal set) use SearchValues — see
collections.md. For encoding whole text buffers to native, see
interop-and-marshalling.md.