Open nblumhardt opened 2 years ago
We've hit the same problem (in our case we wanted TextParser
rather than TokenListParser
).
Unfortunately your suggestion doesn't seem to return a nullable when working with value types. This example compiles even though it assigns the result to a non-nullable variable:
using System;
using Superpower;
using Superpower.Parsers;
#nullable enable
public class Program
{
public static void Main()
{
TextParser<char> a = Character.EqualTo('a');
TextParser<char> shouldBeNullable = a.OptionalOrNull();
}
}
public static class Extensions
{
public static TextParser<T?> OptionalOrNull<T>(
this TextParser<T> parser)
{
return parser != null
? parser.Select(r => (T?) r).Or(Parse.Return<T?>(default))
: throw new ArgumentNullException(nameof(parser));
}
}
The best solution I've found is to have 2 overloads of the extension method.
In the following sample, the return type is nullable as it should be:
using System;
using Superpower;
using Superpower.Parsers;
#nullable enable
public class Program
{
public static void Main()
{
TextParser<char> a = Character.EqualTo('a');
TextParser<char?> correctlyNullable = a.OptionalOrNull();
}
}
internal static class TextParserClassExtensions
{
public static TextParser<T?> OptionalOrNull<T>(this TextParser<T> parser)
where T : class
{
return parser != null
? parser.Select(r => (T?) r).Or(Parse.Return<T?>(null))
: throw new ArgumentNullException(nameof(parser));
}
}
internal static class TextParserParserStructExtensions
{
public static TextParser<T?> OptionalOrNull<T>(this TextParser<T> parser)
where T : struct
{
return parser != null
? parser.Select(r => (T?) r).Or(Parse.Return<T?>(null))
: throw new ArgumentNullException(nameof(parser));
}
}
Hope this helps! Sam Blackburn, Redgate Software
Thank you, Sam! Hoping I'll have a chance to loop back around to this soon.
To cleanly support defaulting optional reference type parsers to
null
I believe we need something like: