Skip to content

Instantly share code, notes, and snippets.

@karenpayneoregon
Last active February 26, 2026 00:46
Show Gist options
  • Select an option

  • Save karenpayneoregon/b0c9daeda4e7f0fea90ec2da31a02a9c to your computer and use it in GitHub Desktop.

Select an option

Save karenpayneoregon/b0c9daeda4e7f0fea90ec2da31a02a9c to your computer and use it in GitHub Desktop.
NextValue multiple versions for teaching
using System.Text.RegularExpressions;
namespace TODO.Classes;
public partial class Helpers
{
/// <summary>
/// Generates the next value in a sequence by incrementing the numeric portion of the input string.
/// </summary>
/// <param name="sender">
/// The input string containing a numeric portion at the end. The numeric portion will be incremented.
/// </param>
/// <param name="incrementBy">
/// The value by which to increment the numeric portion of the input string. Defaults to 1.
/// </param>
/// <returns>
/// A new string with the numeric portion incremented by the specified value, preserving the original length of the numeric portion.
/// </returns>
/// <exception cref="System.FormatException">
/// Thrown if the numeric portion of the input string cannot be parsed as a valid number.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// Thrown if the <paramref name="sender"/> is <c>null</c>.
/// </exception>
public static string NextValue(string sender, int incrementBy = 1)
{
string value = NumbersPattern().Match(sender).Value;
return sender[..^value.Length] + (long.Parse(value) + incrementBy)
.ToString().PadLeft(value.Length, '0');
}
/// <summary>
/// Updates the input string by incrementing the numeric portion at the end of the string.
/// </summary>
/// <param name="sender">
/// A reference to the input string containing a numeric portion at the end.
/// The numeric portion will be incremented, and the updated string will be assigned back to this parameter.
/// </param>
/// <param name="incrementBy">
/// The value by which to increment the numeric portion of the input string. Defaults to 1.
/// </param>
/// <exception cref="System.FormatException">
/// Thrown if the numeric portion of the input string cannot be parsed as a valid number.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// Thrown if the <paramref name="sender"/> is <c>null</c>.
/// </exception>
public static void NextValue(ref string sender, int incrementBy = 1)
{
string value = NumbersPattern().Match(sender).Value;
sender = sender[..^value.Length] + (long.Parse(value) + incrementBy)
.ToString().PadLeft(value.Length, '0');
}
/// <summary>
/// Generates the next value in a sequence by incrementing the numeric portion of the input string,
/// using a <see cref="System.ReadOnlySpan{T}"/> for optimized performance.
/// </summary>
/// <param name="sender">
/// The input string containing a numeric portion at the end. The numeric portion will be incremented.
/// </param>
/// <param name="incrementBy">
/// The value by which to increment the numeric portion of the input string. Defaults to 1.
/// </param>
/// <returns>
/// A new string with the numeric portion incremented by the specified value, preserving the original length of the numeric portion.
/// </returns>
/// <exception cref="System.ArgumentNullException">
/// Thrown if the <paramref name="sender"/> is <c>null</c> or empty.
/// </exception>
public static string NextValueSpan(string sender, int incrementBy = 1)
{
if (string.IsNullOrEmpty(sender)) return sender;
ReadOnlySpan<char> s = sender.AsSpan();
int intLength = s.Length - 1;
while (intLength >= 0 && (uint)(s[intLength] - '0') <= 9) intLength--;
int numberStart = intLength + 1;
if (numberStart == s.Length)
return sender;
ReadOnlySpan<char> numberSpan = s[numberStart..];
long value = 0;
foreach (char c in numberSpan)
value = (value * 10) + (c - '0');
value += incrementBy;
int width = numberSpan.Length;
return string.Create(sender.Length, (sender, numberStart, value, width), static (dest, state) =>
{
var (originalString, start, newValue, w) = state;
originalString.AsSpan(0, start).CopyTo(dest);
Span<char> suffix = dest.Slice(start);
Span<char> fmt = stackalloc char[16];
int fmtLen = 0;
fmt[fmtLen++] = 'D';
int temp = w;
Span<char> digits = stackalloc char[10];
int dlen = 0;
do
{
digits[dlen++] = (char)('0' + (temp % 10));
temp /= 10;
} while (temp > 0);
for (int k = dlen - 1; k >= 0; k--)
fmt[fmtLen++] = digits[k];
if (!newValue.TryFormat(suffix, out _, fmt[..fmtLen], provider: null))
{
newValue.ToString().AsSpan().CopyTo(suffix);
}
});
}
/// <summary>
/// Updates the input string by incrementing the numeric portion at the end of the string,
/// using a <see cref="System.ReadOnlySpan{T}"/> for optimized performance.
/// </summary>
/// <param name="sender">
/// The input string containing a numeric portion at the end. The numeric portion will be incremented.
/// </param>
/// <param name="incrementBy">
/// The value by which to increment the numeric portion of the input string. Defaults to 1.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// Thrown if the <paramref name="sender"/> is <c>null</c> or empty.
/// </exception>
public static void NextValueSpan(ref string sender, int incrementBy = 1)
=> sender = NextValueSpan(sender, incrementBy);
[GeneratedRegex("[0-9]+$")]
private static partial Regex NumbersPattern();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment