# String.Create with Spans

One new C# feature with .NET 9 is the ability to define `allows ref struct` as a generic type constraint. It sounds contradictory to refer to this as a constraint, because it *allows* more types to be used with the given method. However, it can also limit how those generic type parameters maybe used in methods. *Allowing ref struct*s allows *ref struct* types to be used as generic type parameters. The most common *ref struct* types are the built-in `Span<T>` and `ReadOnlySpan<T>` but this constraint allows for any custom *ref struct*s as well. In C# [ref struct](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/ref-struct) types are special as they must live on the stack, and must not escape to the managed heap.

The C# compiler makes sure that *ref struct* types are used correctly, and in this sense, it poses as a constraint. For example, in the code snippet below `MyType` compiles without the constraint:

```csharp
public class MyType<T> // where T : allows ref struct
{
    private T _field;
    public T MyCreate(Func<T> myfunc)
    {
        var value = myfunc();
        _field = value;
        return value;
    }
}
```

However, if we uncomment the `where T : allows ref struct` constraint, the compiler issues the following error for `_field`: *Field or auto-implemented property cannot be of type 'T' unless it is an instance member of a ref struct.*

> Note, that this is not a new limitation, as if the type was not generic, we would get the same error when using a *ref struct* (such as `Span<T>`) in place of the `T`.

## Usage

Overall, this new language feature allows writing generic code, that allows the usage of `Span<T` and `ReadOnlySpan<T>` types. The class library in .NET 9 already uses this feature in two particularly useful places.

### Alternate Dictionary Lookup

The first is [IAlternateEqualityComparer](https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAlternateEqualityComparer.cs,0761573e4ab97e02,references), which is an interface that is implemented by many built-in comparers (`OrdinalComparer`,  `OrdinalIgnoreCaseComparer`, etc.) and it allows for collections like `Dictionary<K,V` to fetch the values of entries with a `string` key, but based on a `ReadOnlySpan<char>` input argument. I [explored](https://blog.ladeak.net/posts/dictionary-alternate) an early preview version of this feature in a previous post, but please note that the signature has changed by the time of the final release of .NET 9.

### String Create

A second impactful place is allowing *ref struct* parameters with the [string.Create](https://learn.microsoft.com/en-us/dotnet/api/system.string.create?view=net-9.0) method. This method has 3 parameters:

- the size of the desired `string`
- `TState` that can be any custom type to hold supporting values of the `string` creation
- a `SpanAction<char, TState>`, that is a callback to initialize the `string`

For the `SpanAction` parameter a developer can pass a callback that formats `TState` into a preallocated buffer by `Create` method. This is quite handy for high-performance scenarios where one prefers to create a `string` while avoiding unnecessary allocations and copies. There is a detailed blog [post](https://www.stevejgordon.co.uk/creating-strings-with-no-allocation-overhead-using-string-create-csharp) about the internals by Steve Gordon.

> Note that knowing the size of the string upfront avoids the need for underlying buffer to 'grow', hence it can be more efficient to string interpolation.

One limitation of this solution was that it could not use a value of `ReadOnlySpan<char>` or `Span<char>` for the `TState` parameter. In this case it had to allocate a reference type, such as `string` or a `byte[]`.

However, in .NET 9 this feature also [allows](https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/String.cs,7dd9a20e8a84bf21) *ref struct*s as type parameters. A `ReadOnlySpan<T>` can be passed now as an input argument:


```csharp
ReadOnlySpan<char> data = "hello";
string.Create(data.Length, data, static (destination, p) => p.CopyTo(destination));
```

### Custom Code

This feature is not limited to the BCL, developers can also use it in their application code. Generic types and methods may define this constraint:

```csharp
public int MyCreate<T>(T data, Func<T, int> func) where T : allows ref struct
{
    return func(data) * 10;
}
```

However, notice that defining the constraint in-itself does not help to work with `Span<T>` and `ReadOnlySpan<T>` types, as the constraint applies to all *ref struct*s, that are not necessarily spans. The above example uses a function (`Func<>` callback) to delegate the responsibility to the caller of this method to handle the actual *ref struct*s, in a similar way as `string.Create` does:

```csharp
ReadOnlySpan<char> data = "hello";
var result = test.MyCreate(data, static input =>
{
    if (int.TryParse(input, out int result))
        return result;
    return -1;
});
```

In the example above, `input` is typed as `ReadOnlySpan<char>`. Note, that for this to work, `Func<>` delegates also allow *ref struct* [type parameters](https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Function.cs,7a86aba051da82dd).

Another approach is allowing *ref struct* types on interfaces. For example, one can create a parser interface that allows ref struct input types:

```csharp
public interface IParser<T> where T : allows ref struct
{
    public int Parse(T data);
}
```

For this post, this interface can be implemented by two types, *SpanParser* and *StringParser*. Note that handling the 'span'-ness of the input is completely done by the type implementing the interface. The interface above, cannot provide span specific information for the input parameter, as the constraint applies to all *ref struct* types.

```csharp
public class SpanParser : IParser<ReadOnlySpan<char>>
{
    public int Parse(ReadOnlySpan<char> data)
    {
        if (int.TryParse(data, out int result))
            return result;
        return -1;
    }
}

public class StringParser : IParser<string>
{
    public int Parse(string data)
    {
        if (int.TryParse(data, out int result))
            return result;
        return -1;
    }
```

If someone would prefer to handle generic input types of `ReadOnlySpan<>`, a type like below could be implemented. This type can be instantiated as `new Counter<char>()` or `new Counter<byte>()`, and the implementation may iterate the input. A further constraint on `T` (for example `IBinaryInteger`) can allow even further processing of the input.

```csharp
public class Counter<T> : IParser<ReadOnlySpan<T>>
{
    public int Parse(ReadOnlySpan<T> data) => data.Length;
}
```

Finally, the above `IParser<T>` interface could be used by a method as shown below. This method accepts a generic input, parses it, applies some custom logic (here the parsed results are multiplied by 10) and returns a result to the caller:

```csharp
int MyCreate<T>(T data, IParser<T> parser) where T : allows ref struct
{
    return parser.Parse(data) * 10;
}

// Use the MyCreate method 👇
ReadOnlySpan<char> data = "hello";
MyCreate(data, new SpanParser());
```

To use this method with a `ReadOnlySpan<char>` a `SpanParser` must be provided as the second argument of this method, because the compiler makes sure that type of `T` matches for both the input arguments.

## Conclusion

This post explains a new C# language feature in .NET 9 that `allows ref struct`s as a constraint for generic type parameters. It shows two examples where this reduces allocation for existing types and methods built into .NET library. Finally, it shows how someone can utilize this feature on custom types and methods, so that `ReadOnlySpan<T>` and `Span<T>` types can become generic type arguments.