Wednesday, December 12, 2018

Quick Introduction to C# Span.


This post is a part of The Second Annual C# Advent. Check out many the other C# related posts there.


Span is a new C# keyword which was introduced in C# version 7.2 on .NET Core 2.1.  C# Span is used in the memory management domain. It can be used to improve memory access performance in many scenarios.

For those of us who also do "Html" development, don't confuse the “Html Span” with the C# Span.  They are completely different in scope and function.

Visual Studio and C# are developed in the open, so we can see what the language designers are considering while adding new features to the C# language.  During the design of the C# 7 new features, Mads Torgersen wrote: 

One feature that could lead to a lot of efficiency would be the ability to have "windows" into arrays - or even onto unmanaged swaths of memory passed along through interop. The amount of copying that could be avoided in some scenarios is probably very significant.

This “window” is what C# Span enables. 

Let's look at a simple case where C# Span can help improve performance.

Example:  C# Substring


This code shows the typical way to get a substring from string using C#.  This is great for getting a portion of a string.

  1. string fullName = "John Jacob Schmidt";
  2. string middleName = fullName.Substring(5, 5);


Now, imagine that not only do we want to get the middle name, but we want to change certain letters in the middleName and have those changes also apply to the fullName.  Without using Span we would have to modify both the middleName string and the fullName string separately.

Span allocates the memory on the stack, the same way that C# Structs are created.  This means the memory is contiguous and can be accessed through the window.

Example:  C# Span slice


Here is similar source code, now using C# Span

  1. Span<char> fullName = "John Jacob Schmidt".ToCharArray().AsSpan();
  2. Span<char> middleName = fullName.Slice(5, 5);
  3. middleName[2] = 'k';
  4. Console.WriteLine(middleName.ToString()); // Prints -> Jakob
  5. Console.WriteLine(fullName.ToString()); // Prints -> John Jakob Schmidt
  6. middleName[6] = 's'// Throws Exception -> System.IndexOutOfRangeException'



On line 1 the Span is allocated.  After that on line 2, a slice is created that encompasses the middleName.  

Line 4, shows changing the third letter of the middleName to the letter 'k'.  Then the middleName and the fullName are both printed.  Notice that the change to the middleName also affected the fullName.

On line 9, we see an access to the seventh character of the middle name.  Since the slice was created to be only 5 characters long, an exception is thrown.  So array bounds are enforced correctly.

Conclusion


This type of memory manipulation was possible before the introduction of C# Span, but the code to do it was very complex and much harder to maintain.  This post shows a simple way to use C# Span.  There are many more uses beyond the simple one shown here.  For further reference look review these articles.

C# Span References:


Code Magazine:
Coding Blast Blog:
MSDN Channel 9:
Mads Torgersen:
MSDN Magazine: