A new feature of C# 11 allows abstract static members with interfaces. This makes it possible to define class methods to be used as a contract with a generic class implementation, e.g. using + and – operators. With .NET 7, numeric types implement many new interfaces. This C# 11 feature is not only about math! The new IParsable
and ISpanParsable
interfaces allow creating objects from strings. As these interfaces can be used with constraints in generic types, parsing strings to create objects is now an easy task with generic implementations. This article shows implementing both the string and the Span version of the parse interfaces and using them with generic types.
IFormattable
Let’s start with an interface which is not new but covers the other side of parsing from a string: converting the object to a string. The IFormattable
interface is available since the early days of .NET. Contrary to the parsable interface, the members defined in the IFormattable
interface are instance members.
With the sample code, the ColorResult
record is split across multiple files using the partial
keyword. In one file, the members of the ColorResult
are defined as shown in the following code snippet. The other files defining the ColorResult
type implement the needed interfaces. ColorResult
contains two byte values. Depending on the game type, the maximum number is different. With the existing game types, these values are in a range from 0 to 5.
With the following implementation of the IFormattable
interface, a string is returned to contain both values from the record. The IFormattable
interface specifies parameters for format strings and cultures. With the ColorResult
implemented, different format strings are not used, and there’s no difference based on the culture, that’s why the parameters are ignored.
ISpanFormattable
To avoid creating new objects that need to be garbage collected, the ISpanFormattable
interface is available since .NET 6. This interface allows writing the string representation of an object to a Span
instance. The following code snippet shows the implementation of the ISpanFormattable
interface. If the size of the span is not big enough, the TryFormat
implementation returns false. Otherwise, the numbers with a separator are written to the span:
The IFormattable
interface implementation is now changed to use the span version by allocating a character array with the required size, and pass a Span
referencing this array to the TryFormat
method:
IParsable and ISpanParsable
To create a new object from the string representation, the interfaces IParsable
and ISpanParsable
are available with .NET 7. These interfaces define static abstract members to convert a string and a span to the generic type as shown in the following code snippets:
You might wonder about the
NotNullWhen
and theMaybeNullWhen
attributes. These attributes are used to tell the compiler that the method returns true if the object is not null, and false if the object is null. The compiler uses this information to avoid null checks. With theTryParse
method, theMaybeNullWhen
attribute is used to tell the compiler that the object is null if the method returns false. TheNotNullWhen
attribute specifies that the parameter is not null the return value is true. This parameter is not an output of this method, so why is this important? With this, the compiler knows, after this method returned successfully, null checks are not requires when the variable is used again.
Implementing ISpanParsable
The ToString
method returns a string containing the members of the ColorType
separated by a colon. Using the list pattern that is available since C# 10 with pattern matching, with the following code snippet, if the pattern matches two characters sparated by a colon, a new ColorField
instance is created and returned. Otherwise, the method returns null:
Using ISpanParsable
With this implementation, a generic method can be implemented to use any type which implements the IParsable
interface. With the generic extension method AddMove
, a constraint is defined to require the IParsable
to be implemented with the generic type TResult
. Then, using the class name TResult
, the Parse
method can be called. With the following code snippet some test string values are passed for parsing and creating a new ColorField
instance. With the game implementation, an algorithm is called get get the correct string values based on the move and the game type:
Other Implementations
You might be interested in how ISpanParsable
is implemented for the existing types. The following code snippet shows the implementation for the IPAddress
type. The TryParse
method is used to parse a span to an IPAddress
instance. The implementation makes use of the IPAddressParser.Parse
method. The implemenation of this method checks if a :
is present in the span, and if so, the span is parsed as an IPv6 address. Otherwise, the span is parsed as an IPv4 address. If the parsing fails, the implementation checks if the method with the Try prefix is used where null
is returned, and otherwise throws a FormatException
. The implementation of the method IP4StringToAddress
to create a long type to represent the IP address which is in turn used to instantiate an IPAddress instance is shown in the following code snippet:
> As you can see with the IPAddress parsing implementation, using unsafe code with C# and Span types can be of practical use. With the implementation of the ColorResult
type where the values are just written to different bytes, the use of unsafe code is not required. In cases like the IPAddress
type to convert the span to an int, it can increase performance what can be of great advantage when you convert many instances in your application.
Take away
Creating a generic implementation to create instances of can now easily be done with the IParsable
and ISpanParsable
interfaces. For the other way around, to convert an object to a string or a span, use the IFormattable
and ISpanFormattable
interfaces. The ISpanFormattable
interface is available since .NET 6, and the IParsable
and ISpanParsable
interfaces are available since .NET 7.
Enjoy learning and programming!
Christian
If you like this article, please support me with a coffee. Thanks!

More Information
The source code of this article is available int the Professional C# book repo within 5_More/Services as part of the MinimalAPIWithGroupsAndTypedResults sample.
More information about C# programming is available in my book and my workshops.
Read more about C# in my book Professional C# and .NET – 2021 Edition
The top image was created using Microsoft Bing Image Creator powered by DALL-E.
> The MaybeNullWhen attribute is used to tell the compiler that the object is null if the method returns false. The compiler uses t
Don’t leave us hanging! What does the compiler use?
My brain is singing “What does the compiler use?” and answering with “Ring-ding-ding-ding-dingeringeding”, which probably isn’t what you intended.
LikeLike
Thanks for your comments! I think it’s fixed now.
LikeLike
Can’t tell if it took the earlier comment or not… can’t see it, but AIA if there are two now.
> The compiler uses this information to avoid null checks. The MaybeNullWhen attribute is used to tell the compiler that the object is null if the method returns false. The compiler uses t
What comes next? You’ve left me hanging! Or is it just starting the beginning of this quote over again?
LikeLike
Thanks for this information! Fixed it now.
LikeLike