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:
Post a Comment