It can point to a managed memory, native memory, or even memory that is allocated on the stack itself. One common use of a span type is array slicing and other types of memory without creating a copy.
NOTE: It is good to keep in mind that the Span is a reference struct that is allocated on the stack rather than the managed heap. As such, it is not applicable in scenarios where you need to store the references to the buffers on the heap.
Span<T> and Memory
The following is an example that demonstrates the creation of a Span<int> from an integer array:
class Program
{
static void Main()
{
int[] array = new int[] { 1, 2, 3, 4, 5 };
Span<int> span = array;
for (int i = 0; i < span.Length; i++)
{
span[i] *= 2;
}
Console.WriteLine("Modified Span<int> elements:");
foreach (var item in span)
{
Console.WriteLine(item);
}
}
}
In the given example, we start by initializing an array of integers with 5 elements.
We then create a Span<Int? named “span” from the array. Since a span provides a view over the memory of the array, modifying the elements of the span also modifies the original array.
Slicing an Array
The following example demonstrates how to use a span in array slicing:
Span<int> slice = array.AsSpan(2, 5);
foreach(var i in slice)
{
Console.WriteLine(i);
}
The “AsSpan” method allows us to slice from the specified start index and include the next number of elements.
This process does not create an array. Instead, it gives us a view of the existing array which is more memory efficient.
Allocating a Memory to Stack
We can use the “stackalloc” keyword to allocate a block of memory on the stack. We can then convert the memory into a Span<Int> which allows us to manipulate the elements with encountering the overhead of the heap memory allocation.
for (int i = 0; i < span.Length; i++)
{
span[i] = i * i;
}
foreach (var s in span)
{
Console.WriteLine(s);
}
Each element in the span is initialized with the square of its index.
Conclusion
In this basic tutorial, we explored the fundamentals of implementing and using the span type for memory efficient operations as introduced in C#.