In modern C# programming, we all strive for efficiency and top-notch performance. And when it comes to dealing with character data, converting a string to a span can be a game-changer. So, in this article, we’ll dive into the process of converting a string to a span and discuss the advantages it offers in terms of performance and memory efficiency.

To download the source code for this article, you can visit our GitHub repository.

With that, let’s dive in.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

What Is a Span<char>?

Let’s imagine we have a sequence of characters and we want a powerful tool to handle it efficiently. That’s where Span<char> comes to the rescue! It’s like a flexible container in C# that holds a contiguous chunk of character data, allowing us to work with it in an awesome way.

Now, here’s the cool part: a Span<char> is designed to be mutable, which means we can modify its content directly. No more creating new string instances every time we need to make a change! This direct access not only saves time but also makes our code more efficient.

When we create a Span<char>, we’re essentially creating a direct view into an existing character data source, such as a string or an array.  This means that a Span<char> doesn’t have its own separate memory allocation. Instead, it borrows the memory from the source it’s pointing to. It’s like having a window into the original data, allowing us to work with it without the overhead of copying or allocating additional memory.

Advantages of Converting a String to a Span<char>

By converting a string to a Span<char>, we can leverage several benefits that enhance the efficiency and flexibility of our code.

Firstly, using a Span<char> allows direct modification of character data, eliminating the need for unnecessary copies. This results in fewer memory allocations and faster code execution, providing a significant speed boost for character-related tasks. Instead of creating new strings or arrays when performing operations like substring extraction or manipulation, we can directly work on the Span<char>. This not only saves memory but also improves code readability and conciseness.

Furthermore, Span<char> offers seamless interoperability by easily passing it to methods that expect arrays or other span-based types. This enhances code flexibility, reusability, and integration with existing APIs.

In scenarios involving performance-critical tasks with character data, such as parsing large amounts of text, working with file I/O, or processing network communication, using a Span<char> can be a game-changer. It optimizes memory usage, reduces unnecessary allocations, and significantly enhances the overall efficiency of our code.

Let’s now explore some of the ways we can convert a string to a Span<char>

Use the ToCharArray Method

We can use the ToCharArray() method to convert a string to a char array, and then return it as a Span<char> from a method:

public Span<char> ConvertStringToSpanUsingToCharArray()
{
    var charArray = _myString.ToCharArray();

    return charArray;
}

Convert a String to a Span With the Unsafe Keyword

When working with unmanaged memory or requiring low-level pointer operations, the unsafe keyword can be used to convert a string to a Span<char>:

public unsafe Span<char> ConvertStringToSpanUsingUnsafe()
{
    unsafe
    {
        var myString = "Hello, World!";
        fixed (char* ptr = myString)
        {
            return new Span<char>(ptr, myString.Length);
        }
    }
}

Here, we use the fixed keyword to pin the myString string in memory, preventing it from being moved by the garbage collector.

Then, we create a Span<char> directly from the pinned memory using a pointer.

If you would like to learn more about unsafe code, refer to our great article Unsafe Code in C#.

However, it’s important to note that working with unsafe code carries potential risks and should be used with caution.

Use the AsSpan() Method

Another straightforward approach is to use the AsSpan() method, which provides a convenient and efficient way to create a ReadOnlySpan<char> directly from a string without the need for intermediate steps:

public ReadOnlySpan<char> ConvertStringToReadOnlySpanUsingAsSpan()
{
    var myString = "Hello, World!";
    var span = myString.AsSpan();

    return span;
}

We simply call the AsSpan() method directly on the myString variable. This creates a ReadOnlySpan<char> that represents a read-only view of the original string’s character data. We can use this ReadOnlySpan<char> to perform various read-only operations, such as searching, iterating, or passing it to methods that accept ReadOnlySpan<char> parameters.

If we need to perform mutable operations and modify the character data directly, we can create a new Span<char> from the ReadOnlySpan<char> by calling ToArray() method:

public Span<char> ConvertStringToSpanUsingAsSpan()
{
    var myString = "Hello, World!";
    var span = myString.AsSpan();

    return span.ToArray();
}

This time, we return a Span<char> created from the ReadOnlySpan<char>. This allows us to work with the character data in a mutable manner. However, it’s important to note that creating a new Span<char> from the ReadOnlySpan<char> involves memory allocation for the new array.

We can choose the approach that best fits our requirements: returning a ReadOnlySpan<char> for read-only access or returning a Span<char> for mutable operations at the cost of memory allocation.

Use Implicit Conversion To Convert a String to a Span

Starting from C# 7.2, there is an implicit conversion from string to ReadOnlySpan<char>. This means we can assign a string to a variable of type ReadOnlySpan<char> without explicitly calling any conversion methods:

public ReadOnlySpan<char> ConvertStringToSpan()
{
    var myString = "Hello, World!";
    ReadOnlySpan<char> span = myString;

    return span;
}

Here, the string  Hello, World!  is implicitly converted to a ReadOnlySpan<char> and assigned to the variable span. This allows us to work with the character data of the string using the Span<char> APIs.

It’s important to note that this implicit conversion creates a read-only view of the string’s character data. If we need to modify the character data, we would need to create a mutable Span<char> using one of the methods we covered earlier.

What Is the Fastest Way to Convert a String to a Span<char>?

After exploring various methods to convert a string to a span, let’s dive into a benchmark to identify the fastest approach:

|                                 Method |       Mean |     Error |    StdDev |     Median |  Gen 0 | Allocated |
|--------------------------------------- |-----------:|----------:|----------:|-----------:|-------:|----------:|
| ConvertStringToReadOnlySpanUsingAsSpan |  0.0000 ns | 0.0000 ns | 0.0000 ns |  0.0000 ns |      - |         - |
|                    ConvertStringToSpan |  0.0610 ns | 0.0287 ns | 0.0269 ns |  0.0651 ns |      - |         - |
|         ConvertStringToSpanUsingUnsafe |  0.8338 ns | 0.0568 ns | 0.0676 ns |  0.8283 ns |      - |         - |
|         ConvertStringToSpanUsingAsSpan | 18.9446 ns | 0.4780 ns | 1.4018 ns | 18.5644 ns | 0.0134 |      56 B |
|    ConvertStringToSpanUsingToCharArray | 21.0052 ns | 0.4551 ns | 1.2687 ns | 20.8637 ns | 0.0134 |      56 B |

Based on the benchmark results, we can identify the ConvertStringToReadOnlySpanUsingAsSpan() method as the most performant. It showcases a slight speed advantage over other methods, although exact execution times in nanoseconds are subject to environmental variations.

The ConvertStringToReadOnlySpanUsingAsSpan() method capitalizes on the AsSpan() method provided by the string type. By utilizing this feature, it efficiently obtains a read-only span directly from the string, ensuring an optimized conversion process.

While the variance in performance among the different conversion methods is minimal, it’s important to consider factors beyond execution time when selecting an appropriate method. Apart from performance, aspects such as code readability and adherence to specific application requirements should also be taken into account.

When deciding on a conversion method, it’s advisable to consider additional considerations such as memory allocation, safety, and the overall performance needs of our code. By holistically evaluating these factors, we can make informed decisions that align with the specific requirements and objectives of your application.

Conclusion

Converting a string to a span unlocks powerful capabilities for efficiently working with character data. By using the ToCharArray method, the unsafe keyword, or the AsSpan() method, we can easily create a Span<char> and tap into its performance benefits. Of course, the choice comes down to our individual requirements, so take those into consideration when picking a solution.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!