August 23, 2026

Parsing Extensions

An idea from Nick Chapsis as shown here https://www.youtube.com/watch?v=lqbYURwM0bw, althought I added the TryParse with default value. These extensions that allow you to call the Parse function on a string or span. This will work with all the Basic types because they will have the static ISpanParsable interface defined for them.

public static class ParsableExtensions
{
	// SPAN Parsing
	
    /// <summary>
    /// Parse a span of characters for a given type <typeparamref name="T"/>
    /// </summary>
    /// <typeparam name="T">Type that supports an ISpanParsable<typeparamref name="T"/> interface</typeparam>
    /// <param name="input">span of characters to parse</param>
    /// <param name="fp">format provider</param>
    /// <returns>The parsed value, will throw an exception if the parsing faile</returns>
    public static T Parse<T>(this ReadOnlySpan<char> input, IFormatProvider? fp = null)
      where T : ISpanParsable<T>
    {
        return T.Parse(input, fp);
    }

    /// <summary>
    /// Parse a span of characters for a given type <typeparamref name="T"/>, the parsed value is returned as an out parameter
    /// </summary>
    /// <typeparam name="T">Type that supports an ISpanParsable<typeparamref name="T"/> interface</typeparam>
    /// <param name="input">span of characters to parse</param>
    /// <param name="fp">format provider</param>
    /// <returns>whether the parse succeeded or not</returns>
    public static bool TryParse<T>(this ReadOnlySpan<char> input, IFormatProvider fp, out T? value)
      where T : ISpanParsable<T>
    {
        return T.TryParse(input, fp, out value);
    }

    /// <summary>
    /// Parse a span of characters for a given type <typeparamref name="T"/>
    /// </summary>
    /// <typeparam name="T">Type that supports an ISpanParsable<typeparamref name="T"/> interface</typeparam>
    /// <param name="input">span of characters to parse</param>
    /// <param name="defaultValue">The value to return if the parsing failed</param>
    /// <returns>The parsed value if the span was successfully parsed, the default value otherwise</returns>
    public static T Parse<T>(this ReadOnlySpan<char> input, T defaultValue)
      where T : ISpanParsable<T>
    {
        T result = T.TryParse(input, null, out T? value) ? value : defaultValue;
        return result;
    }

	/////////////////////////////////////////////////////////////////////////////////
	// STRING parsing

	/// <summary>
	/// Parse a string for a given type <typeparamref name="T"/>
	/// </summary>
	/// <typeparam name="T">Type that supports an ISpanParsable<typeparamref name="T"/> interface</typeparam>
	/// <param name="input">string to parse</param>
	/// <param name="fp">format provider</param>
	/// <returns>The parsed value, will throw an exception if the parsing faile</returns>
	public static T Parse<T>(this string input, IFormatProvider? fp = null)
	  where T : ISpanParsable<T>
	{
		return T.Parse(input, fp);
	}

	/// <summary>
	/// Parse a string for a given type <typeparamref name="T"/>, the parsed value is returned as an out parameter
	/// </summary>
	/// <typeparam name="T">Type that supports an ISpanParsable<typeparamref name="T"/> interface</typeparam>
	/// <param name="input">string to parse</param>
	/// <param name="fp">format provider</param>
	/// <returns>whether the parse succeeded or not</returns>
	public static bool TryParse<T>(this string input, IFormatProvider fp, out T? value)
	  where T : ISpanParsable<T>
	{
		return T.TryParse(input, fp, out value);
	}

	/// <summary>
	/// Parse a string for a given type <typeparamref name="T"/>
	/// </summary>
	/// <typeparam name="T">Type that supports an ISpanParsable<typeparamref name="T"/> interface</typeparam>
	/// <param name="input">string to parse</param>
	/// <param name="defaultValue">The value to return if the parsing failed</param>
	/// <returns>The parsed value if the string was successfully parsed, the default value otherwise</returns>
	public static T Parse<T>(this string input, T defaultValue)
	  where T : ISpanParsable<T>
	{
		T result = T.TryParse(input, null, out T? value) ? value : defaultValue;
		return result;
	}
}

Here are some examples on how to call them. I have used the Shouldy package to perform the assertions.

int resSpan = "  54 ".AsSpan().Parse(); // Span Parse
resSpan.ShouldEqual(54);

int resStr = " 27  ".Parse();   // String parse
resStr.ShouldEqual(27);
	
var action = () => { int res2Str = "   ".Parse(); }; // String parse that throws a format exception
action.ShouldThrow(); 

int res2Span = "   ".AsSpan().Parse(-1); // Span parse with default value
res2Span.ShouldEqual(-1);

No comments: