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
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.
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.
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:
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
IParsable and ISpanParsable
To create a new object from the string representation, the interfaces
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
MaybeNullWhenattributes. 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 the
MaybeNullWhenattribute is used to tell the compiler that the object is null if the method returns false. The
NotNullWhenattribute 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.
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:
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
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:
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.
Creating a generic implementation to create instances of can now easily be done with the
ISpanParsable interfaces. For the other way around, to convert an object to a string or a span, use the
ISpanFormattable interfaces. The
ISpanFormattable interface is available since .NET 6, and the
ISpanParsable interfaces are available since .NET 7.
Enjoy learning and programming!
If you like this article, please support me with a coffee. Thanks!
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.
8 thoughts on “Converting Strings to .NET Objects – IParsable and ISpanParsable”
> 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.
Thanks for your comments! I think it’s fixed now.
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?
Thanks for this information! Fixed it now.